import { CdkTrapFocus } from '@angular/cdk/a11y';
import { MediaMatcher } from '@angular/cdk/layout';
import { CdkOption, CdkListbox } from '@angular/cdk/listbox';
import * as i2 from '@angular/cdk/overlay';
import { OverlayModule } from '@angular/cdk/overlay';
import { NgTemplateOutlet, DatePipe } from '@angular/common';
import * as i0 from '@angular/core';
import { Injectable, input, booleanAttribute, output, signal, computed, ChangeDetectionStrategy, Component, Pipe, inject, model, NgModule } from '@angular/core';
import * as i1 from '@angular/forms';
import { FormsModule } from '@angular/forms';
import { elementDown2 } from '@siemens/element-icons';
import { isValid, SiCalendarButtonComponent, SiDatepickerComponent, SiDatepickerDirective } from '@siemens/element-ng/datepicker';
import { addIcons, SiIconComponent } from '@siemens/element-ng/icon';
import { BOOTSTRAP_BREAKPOINTS } from '@siemens/element-ng/resize-observer';
import { SiSearchBarComponent } from '@siemens/element-ng/search-bar';
import { t, SiTranslatePipe } from '@siemens/element-translate-ng/translate';
import { SiNumberInputComponent } from '@siemens/element-ng/number-input';
import { SiSelectComponent, SiSelectSingleValueDirective, SiSelectSimpleOptionsDirective } from '@siemens/element-ng/select';

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
/**
 * Service to transform and calculate with DateRangeFilter objects.
 */
class SiDateRangeCalculationService {
    /**
     * Calculates the start and end dates of a DateRangeFilter.
     * @param filter - The date range filter object to be resolved.
     * @param options - Options for time handling
     * @returns The resolved result in form of a ResolvedDateRange object.
     */
    resolveDateRangeFilter(filter, options) {
        const ref = filter.point1 === 'now' ? new Date() : new Date(filter.point1);
        const withTime = options?.withTime ?? true;
        if (!withTime) {
            this.removeTime(ref);
        }
        if (filter.point2 instanceof Date) {
            const point2 = withTime ? filter.point2 : this.removeTime(new Date(filter.point2));
            return this.normalize(ref, point2, options?.skipNormalization);
        }
        const offset = filter.point2;
        switch (filter.range) {
            case undefined:
            case 'before':
                return this.normalize(ref, this.datePlusOffset(ref, -offset), options?.skipNormalization);
            case 'after':
                return this.normalize(ref, this.datePlusOffset(ref, offset), options?.skipNormalization);
            case 'within':
                return this.normalize(this.datePlusOffset(ref, -offset), this.datePlusOffset(ref, offset), options?.skipNormalization);
        }
    }
    datePlusOffset(date, offset) {
        return new Date(date.getTime() + offset);
    }
    normalize(date1, date2, skip) {
        const valid = !isNaN(date1.getTime()) && !isNaN(date2.getTime());
        return skip
            ? { start: date1, end: date2, valid }
            : date1 < date2
                ? { start: date1, end: date2, valid }
                : { start: date2, end: date1, valid };
    }
    /**
     * Utility to reset the time attributes to 0 (hours/minutes/seconds/milliseconds).
     */
    removeTime(date) {
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);
        return date;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiDateRangeCalculationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiDateRangeCalculationService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiDateRangeCalculationService, decorators: [{
            type: Injectable,
            args: [{ providedIn: 'root' }]
        }] });

const ONE_MINUTE = 60 * 1000;
const ONE_DAY = ONE_MINUTE * 60 * 24;

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
class SiRelativeDateComponent {
    /** @defaultValue 0 */
    // eslint-disable-next-line @angular-eslint/prefer-signal-model
    value = input(0, ...(ngDevMode ? [{ debugName: "value" }] : []));
    /** @defaultValue false */
    enableTimeSelection = input(false, { ...(ngDevMode ? { debugName: "enableTimeSelection" } : {}), transform: booleanAttribute });
    valueLabel = input.required(...(ngDevMode ? [{ debugName: "valueLabel" }] : []));
    unitLabel = input.required(...(ngDevMode ? [{ debugName: "unitLabel" }] : []));
    valueChange = output();
    internalValue = signal(0, ...(ngDevMode ? [{ debugName: "internalValue" }] : []));
    offset = signal(0, ...(ngDevMode ? [{ debugName: "offset" }] : []));
    unit = signal('days', ...(ngDevMode ? [{ debugName: "unit" }] : []));
    fullOffsetList = [
        {
            type: 'option',
            value: 'minutes',
            label: t(() => $localize `:@@SI_DATE_RANGE_FILTER.MINUTES:Minutes`),
            offset: ONE_MINUTE
        },
        {
            type: 'option',
            value: 'hours',
            label: t(() => $localize `:@@SI_DATE_RANGE_FILTER.HOURS:Hours`),
            offset: 60 * ONE_MINUTE
        },
        {
            type: 'option',
            value: 'days',
            label: t(() => $localize `:@@SI_DATE_RANGE_FILTER.DAYS:Days`),
            offset: ONE_DAY
        },
        {
            type: 'option',
            value: 'weeks',
            label: t(() => $localize `:@@SI_DATE_RANGE_FILTER.WEEKS:Weeks`),
            offset: 7 * ONE_DAY
        },
        {
            type: 'option',
            value: 'months',
            label: t(() => $localize `:@@SI_DATE_RANGE_FILTER.MONTHS:Months`),
            offset: 30 * ONE_DAY
        },
        {
            type: 'option',
            value: 'years',
            label: t(() => $localize `:@@SI_DATE_RANGE_FILTER.YEARS:Years`),
            offset: 365 * ONE_DAY
        }
    ];
    offsetList = computed(() => this.enableTimeSelection()
        ? this.fullOffsetList
        : this.fullOffsetList.filter(item => item.offset >= ONE_DAY), ...(ngDevMode ? [{ debugName: "offsetList" }] : []));
    ngOnChanges(changes) {
        const value = this.value();
        if (changes.value && value !== this.internalValue()) {
            this.internalValue.set(value);
            this.calculateOffset();
        }
    }
    calculateOffset() {
        const offsetList = this.offsetList();
        let unit = '';
        if (offsetList.length) {
            this.offset.set(0);
            unit = offsetList[0].value;
        }
        for (let i = offsetList.length - 1; i >= 0; i--) {
            const item = offsetList[i];
            const raw = this.internalValue() / item.offset;
            const rounded = Math.round(raw);
            if (rounded > 0 && Math.abs(raw - rounded) < 0.001) {
                this.offset.set(rounded);
                unit = item.value;
                break;
            }
        }
        this.changeUnit(unit);
    }
    updateValue(offset) {
        this.offset.set(offset);
        const item = this.offsetList().find(x => x.value === this.unit());
        this.internalValue.set(offset * item.offset);
        this.valueChange.emit(this.internalValue());
    }
    changeUnit(newUnit) {
        this.unit.set(newUnit);
        const item = this.offsetList().find(x => x.value === this.unit());
        this.offset.set(Math.max(1, Math.round(this.internalValue() / item.offset)));
        this.internalValue.set(this.offset() * item.offset);
        this.valueChange.emit(this.internalValue());
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiRelativeDateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.8", type: SiRelativeDateComponent, isStandalone: true, selector: "si-relative-date", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, enableTimeSelection: { classPropertyName: "enableTimeSelection", publicName: "enableTimeSelection", isSignal: true, isRequired: false, transformFunction: null }, valueLabel: { classPropertyName: "valueLabel", publicName: "valueLabel", isSignal: true, isRequired: true, transformFunction: null }, unitLabel: { classPropertyName: "unitLabel", publicName: "unitLabel", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { valueChange: "valueChange" }, usesOnChanges: true, ngImport: i0, template: "<si-number-input\n  class=\"form-control mb-4\"\n  [aria-label]=\"valueLabel()\"\n  [ngModel]=\"offset()\"\n  (ngModelChange)=\"updateValue($event)\"\n/>\n<si-select\n  class=\"form-control\"\n  min=\"0\"\n  [ariaLabel]=\"unitLabel()\"\n  [options]=\"offsetList()\"\n  [ngModel]=\"unit()\"\n  (ngModelChange)=\"changeUnit($event)\"\n/>\n", styles: [".form-control{min-inline-size:0}\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: SiNumberInputComponent, selector: "si-number-input", inputs: ["min", "max", "step", "value", "unit", "showButtons", "aria-label", "inputId", "disabled", "readonly", "placeholder", "errormessageId"], outputs: ["valueChange"] }, { kind: "component", type: SiSelectComponent, selector: "si-select", inputs: ["id", "ariaLabel", "labelledby", "filterPlaceholder", "noResultsFoundLabel", "placeholder", "readonly", "errormessageId", "hasFilter"], outputs: ["openChange"] }, { kind: "directive", type: SiSelectSingleValueDirective, selector: "si-select:not([multi])" }, { kind: "directive", type: SiSelectSimpleOptionsDirective, selector: "si-select[options]", inputs: ["options", "optionEqualCheckFn"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiRelativeDateComponent, decorators: [{
            type: Component,
            args: [{ selector: 'si-relative-date', imports: [
                        FormsModule,
                        SiNumberInputComponent,
                        SiSelectComponent,
                        SiSelectSingleValueDirective,
                        SiSelectSimpleOptionsDirective
                    ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<si-number-input\n  class=\"form-control mb-4\"\n  [aria-label]=\"valueLabel()\"\n  [ngModel]=\"offset()\"\n  (ngModelChange)=\"updateValue($event)\"\n/>\n<si-select\n  class=\"form-control\"\n  min=\"0\"\n  [ariaLabel]=\"unitLabel()\"\n  [options]=\"offsetList()\"\n  [ngModel]=\"unit()\"\n  (ngModelChange)=\"changeUnit($event)\"\n/>\n", styles: [".form-control{min-inline-size:0}\n"] }]
        }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], enableTimeSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableTimeSelection", required: false }] }], valueLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueLabel", required: true }] }], unitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "unitLabel", required: true }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
class PresetMatchFilterPipe {
    transform(value, term) {
        return !term ? true : value.toLowerCase().includes(term.toLowerCase());
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: PresetMatchFilterPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
    static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.8", ngImport: i0, type: PresetMatchFilterPipe, isStandalone: true, name: "presetMatchFilter" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: PresetMatchFilterPipe, decorators: [{
            type: Pipe,
            args: [{ name: 'presetMatchFilter', pure: true }]
        }] });
class SiDateRangeFilterComponent {
    service = inject(SiDateRangeCalculationService);
    mediaMatcher = inject(MediaMatcher);
    smallScreen = this.mediaMatcher.matchMedia(`(max-width: ${BOOTSTRAP_BREAKPOINTS.mdMinimum}px)`).matches;
    /** The filter range object */
    range = model.required(...(ngDevMode ? [{ debugName: "range" }] : []));
    /** List of preset time ranges. When not present or empty, the preset section won't show */
    presetList = input(...(ngDevMode ? [undefined, { debugName: "presetList" }] : []));
    /**
     * Determines if there's a search field for the preset list
     *
     * @defaultValue true
     */
    presetSearch = input(true, { ...(ngDevMode ? { debugName: "presetSearch" } : {}), transform: booleanAttribute });
    /**
     * Determines if time is selectable or only dates
     *
     * @defaultValue false
     */
    enableTimeSelection = input(false, { ...(ngDevMode ? { debugName: "enableTimeSelection" } : {}), transform: booleanAttribute });
    /**
     * Determines whether to show input fields or a date-range calendar in basic mode.
     * When time selection is enabled, this has no effect and input fields are always shown.
     *
     * @defaultValue 'calendar'
     */
    basicMode = input('calendar', ...(ngDevMode ? [{ debugName: "basicMode" }] : []));
    /**
     * Reverses the order of the from/to fields
     *
     * @defaultValue false
     */
    reverseInputFields = input(false, { ...(ngDevMode ? { debugName: "reverseInputFields" } : {}), transform: booleanAttribute });
    /**
     * Determines whether to show the 'Apply' button
     *
     * @defaultValue false
     */
    showApplyButton = input(false, { ...(ngDevMode ? { debugName: "showApplyButton" } : {}), transform: booleanAttribute });
    /**
     * Hides the advanced mode if input allows
     *
     * @defaultValue false
     */
    hideAdvancedMode = input(false, { ...(ngDevMode ? { debugName: "hideAdvancedMode" } : {}), transform: booleanAttribute });
    /**
     * label for the "Reference point" title
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.REF_POINT:Reference point`)
     * ```
     */
    refLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.REF_POINT:Reference point`), ...(ngDevMode ? [{ debugName: "refLabel" }] : []));
    /**
     * label for the "Reference point" title
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.FROM:From`)
     * ```
     */
    fromLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.FROM:From`), ...(ngDevMode ? [{ debugName: "fromLabel" }] : []));
    /**
     * label for the "Reference point" title
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.TO:To`)
     * ```
     */
    toLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.TO:To`), ...(ngDevMode ? [{ debugName: "toLabel" }] : []));
    /**
     * label for the "Range" title
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.RANGE:Range`)
     * ```
     */
    rangeLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.RANGE:Range`), ...(ngDevMode ? [{ debugName: "rangeLabel" }] : []));
    /**
     * label for the "Today" checkbox
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.TODAY:Today`)
     * ```
     */
    todayLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.TODAY:Today`), ...(ngDevMode ? [{ debugName: "todayLabel" }] : []));
    /**
     * label for the "Now" checkbox
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.NOW:Now`)
     * ```
     */
    nowLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.NOW:Now`), ...(ngDevMode ? [{ debugName: "nowLabel" }] : []));
    /**
     * label for "Date" field / radio button
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.DATE:Date`)
     * ```
     */
    dateLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.DATE:Date`), ...(ngDevMode ? [{ debugName: "dateLabel" }] : []));
    /**
     * label for the "Preview" title
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.PREVIEW:Preview`)
     * ```
     */
    previewLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.PREVIEW:Preview`), ...(ngDevMode ? [{ debugName: "previewLabel" }] : []));
    /**
     * Placeholder for date fields
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.DATE_PLACEHOLDER:Select date`)
     * ```
     */
    datePlaceholder = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.DATE_PLACEHOLDER:Select date`), ...(ngDevMode ? [{ debugName: "datePlaceholder" }] : []));
    /**
     * label for the "Before" toggle
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.BEFORE:Before`)
     * ```
     */
    beforeLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.BEFORE:Before`), ...(ngDevMode ? [{ debugName: "beforeLabel" }] : []));
    /**
     * label for the "After" toggle
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.AFTER:After`)
     * ```
     */
    afterLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.AFTER:After`), ...(ngDevMode ? [{ debugName: "afterLabel" }] : []));
    /**
     * label for the "Within" toggle
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.WITHIN:Within`)
     * ```
     */
    withinLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.WITHIN:Within`), ...(ngDevMode ? [{ debugName: "withinLabel" }] : []));
    /**
     * label for the "value" number input
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.VALUE:Value`)
     * ```
     */
    valueLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.VALUE:Value`), ...(ngDevMode ? [{ debugName: "valueLabel" }] : []));
    /**
     * label for the "Unit" select
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.UNIT:Unit`)
     * ```
     */
    unitLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.UNIT:Unit`), ...(ngDevMode ? [{ debugName: "unitLabel" }] : []));
    /**
     * label for the "search" input
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.SEARCH:Search`)
     * ```
     */
    searchLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.SEARCH:Search`), ...(ngDevMode ? [{ debugName: "searchLabel" }] : []));
    /**
     * label for the "search" input
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.PRESETS:Presets`)
     * ```
     */
    presetLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.PRESETS:Presets`), ...(ngDevMode ? [{ debugName: "presetLabel" }] : []));
    /**
     * label for the "advanced" switch
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.ADVANCED:Advanced`)
     * ```
     */
    advancedLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.ADVANCED:Advanced`), ...(ngDevMode ? [{ debugName: "advancedLabel" }] : []));
    /**
     * label for the "apply" switch
     *
     * @defaultValue
     * ```
     * t(() => $localize`:@@SI_DATE_RANGE_FILTER.APPLY:Apply`)
     * ```
     */
    applyLabel = input(t(() => $localize `:@@SI_DATE_RANGE_FILTER.APPLY:Apply`), ...(ngDevMode ? [{ debugName: "applyLabel" }] : []));
    /** Event fired when the apply button has been clicked */
    applyClicked = output();
    /** Base configuration on how the dates should be displayed, parts of it may be overwritten internally. */
    datepickerConfig = input(...(ngDevMode ? [undefined, { debugName: "datepickerConfig" }] : []));
    icons = addIcons({ elementDown2 });
    advancedMode = signal(false, ...(ngDevMode ? [{ debugName: "advancedMode" }] : []));
    dateRange = signal({ start: undefined, end: undefined }, ...(ngDevMode ? [{ debugName: "dateRange" }] : []));
    point1Now = signal(true, ...(ngDevMode ? [{ debugName: "point1Now" }] : []));
    point2Mode = signal('duration', ...(ngDevMode ? [{ debugName: "point2Mode" }] : []));
    point1date = signal(this.getDateNow(), ...(ngDevMode ? [{ debugName: "point1date" }] : []));
    point2date = signal(this.getDateNow(), ...(ngDevMode ? [{ debugName: "point2date" }] : []));
    point2offset = signal(0, ...(ngDevMode ? [{ debugName: "point2offset" }] : []));
    point2range = signal('before', ...(ngDevMode ? [{ debugName: "point2range" }] : []));
    calculatedRange = computed(() => this.resolve(this.range()), ...(ngDevMode ? [{ debugName: "calculatedRange" }] : []));
    pipeFormat = computed(() => this.enableTimeSelection()
        ? (this.datepickerConfig()?.dateTimeFormat ?? 'short')
        : (this.datepickerConfig()?.dateFormat ?? 'shortDate'), ...(ngDevMode ? [{ debugName: "pipeFormat" }] : []));
    datepickerConfigInternal = computed(() => ({
        ...(this.datepickerConfig() ?? {}),
        enableDateRange: false,
        showTime: this.enableTimeSelection(),
        mandatoryTime: this.enableTimeSelection()
    }), ...(ngDevMode ? [{ debugName: "datepickerConfigInternal" }] : []));
    dateRangeConfig = computed(() => ({
        ...(this.datepickerConfig() ?? {}),
        enableDateRange: true
    }), ...(ngDevMode ? [{ debugName: "dateRangeConfig" }] : []));
    filteredPresetList = computed(() => {
        const timeFilter = (item) => {
            const timeOnly = item.type === 'custom' ? item.timeOnly : item.offset < ONE_DAY;
            return this.enableTimeSelection() || !timeOnly;
        };
        return (this.presetList() ?? []).filter(timeFilter);
    }, ...(ngDevMode ? [{ debugName: "filteredPresetList" }] : []));
    focusedDate = computed(() => {
        const range = this.dateRange();
        const date = range.end ?? range.start;
        return isValid(date) ? date : undefined;
    }, ...(ngDevMode ? [{ debugName: "focusedDate" }] : []));
    presetFilter = signal('', ...(ngDevMode ? [{ debugName: "presetFilter" }] : []));
    presetOpen = signal(false, ...(ngDevMode ? [{ debugName: "presetOpen" }] : []));
    inputMode = computed(() => this.basicMode() === 'input' || this.enableTimeSelection(), ...(ngDevMode ? [{ debugName: "inputMode" }] : []));
    ngOnChanges(changes) {
        if (changes.enableTimeSelection ||
            changes.datepickerConfig ||
            (changes.range && this.rangeChanged(changes.range.previousValue, changes.range.currentValue))) {
            this.updateFromRange(this.range());
        }
        if ((changes.basicMode || changes.enableTimeSelection) &&
            this.inputMode() &&
            !this.advancedMode()) {
            this.point2Mode.set('date');
            this.point2Changed();
        }
    }
    getDateNow() {
        const now = new Date();
        if (!this.enableTimeSelection()) {
            this.service.removeTime(now);
        }
        return now;
    }
    rangeChanged(oldRange, newRange) {
        return (!oldRange || // eslint-disable-line @typescript-eslint/prefer-optional-chain
            oldRange.point1 !== newRange.point1 ||
            oldRange.point2 !== newRange.point2 ||
            oldRange.range !== newRange.range);
    }
    updateFromRange(rangeVal) {
        this.point1Now.set(rangeVal.point1 === 'now');
        this.point1date.set(rangeVal.point1 === 'now' ? this.getDateNow() : rangeVal.point1);
        if (rangeVal.point2) {
            this.point2Mode.set(rangeVal.point2 instanceof Date ? 'date' : 'duration');
            this.point2date.set(rangeVal.point2 instanceof Date ? rangeVal.point2 : this.getDateNow());
            this.point2range.set(rangeVal.range ?? 'before');
            this.point2offset.set(rangeVal.point2 instanceof Date
                ? Math.abs(Math.round(this.point1date().getTime() - rangeVal.point2.getTime()))
                : rangeVal.point2);
        }
        if ((this.point1Now() && this.basicMode() !== 'input') || this.point2Mode() !== 'date') {
            this.advancedMode.set(true);
        }
        else {
            this.advancedMode.set(false);
            this.updateDateRange();
        }
    }
    resolve(range, skipNormalization) {
        return this.service.resolveDateRangeFilter(range, {
            withTime: this.enableTimeSelection(),
            skipNormalization
        });
    }
    updateDateRange(range = this.range()) {
        const calculatedRange = this.resolve(range);
        this.dateRange.set({ start: calculatedRange.start, end: calculatedRange.end });
    }
    updateOnModeChange() {
        if (this.advancedMode()) {
            const calculatedRange = this.resolve(this.range());
            this.point1date.set(calculatedRange.start);
            this.point2Mode.set('duration');
            this.point2range.set('after');
            this.point2offset.set(Math.abs(calculatedRange.end.getTime() - calculatedRange.start.getTime()));
            this.updateRange();
        }
        else {
            this.updateSimpleMode(this.range());
        }
    }
    updateSimpleMode(newRange) {
        if (this.inputMode()) {
            // input mode supports `now`, so point1 needs to remain unchanged
            if (newRange.point1 === 'now') {
                this.point1Now.set(true);
                this.point1date.set(this.getDateNow());
            }
            else {
                this.point1Now.set(false);
                this.point1date.set(newRange.point1);
            }
            const calculatedRange = this.resolve(newRange, true);
            this.point2Mode.set('date');
            this.point2date.set(calculatedRange.end);
            this.updateRange();
        }
        else {
            this.point1Now.set(false);
            this.updateDateRange(newRange);
            this.updateFromDateRange();
        }
    }
    updateRange() {
        const point2isDate = this.point2Mode() === 'date';
        const newRange = {
            point1: this.point1Now() ? 'now' : this.point1date(),
            point2: point2isDate ? this.point2date() : this.point2offset(),
            range: point2isDate ? undefined : this.point2range()
        };
        this.range.update(old => ({ ...old, ...newRange }));
    }
    updateFromDateRange(dateRange) {
        if (dateRange) {
            this.dateRange.set(dateRange);
        }
        const range = this.dateRange();
        const startDate = range.start ?? this.getDateNow();
        const endDate = range.end ?? this.getDateNow();
        this.point1date.set(startDate);
        this.point2date.set(endDate);
        this.point2Mode.set('date');
        this.point2offset.set(0);
        this.updateRange();
    }
    point1Changed() {
        if (this.point1Now()) {
            this.point1date.set(this.getDateNow());
        }
        this.updateRange();
    }
    point2Changed() {
        if (this.point2Mode() === 'date') {
            if (!(this.range().point2 instanceof Date)) {
                const calculatedRange = this.resolve(this.range());
                if (calculatedRange.valid) {
                    this.point2date.set(this.point1date() < calculatedRange.end ? calculatedRange.start : calculatedRange.end);
                }
            }
        }
        else {
            if (this.range().point2 instanceof Date) {
                const calculatedRange = this.resolve(this.range());
                this.point2offset.set(Math.round(calculatedRange.end.getTime() - calculatedRange.start.getTime()));
            }
        }
        this.updateRange();
    }
    selectPresetItem(event, item) {
        const newRange = item.type === 'custom'
            ? item.calculate(item, this.range())
            : { point1: 'now', range: 'before', point2: item.offset };
        if (this.advancedMode()) {
            this.updateFromRange(newRange);
        }
        else {
            this.updateSimpleMode(newRange);
        }
        if (this.smallScreen) {
            // Prevent re-opening the dropdown when pressing enter on the selected item
            event.preventDefault();
            this.presetOpen.set(false);
        }
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiDateRangeFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.8", type: SiDateRangeFilterComponent, isStandalone: true, selector: "si-date-range-filter", inputs: { range: { classPropertyName: "range", publicName: "range", isSignal: true, isRequired: true, transformFunction: null }, presetList: { classPropertyName: "presetList", publicName: "presetList", isSignal: true, isRequired: false, transformFunction: null }, presetSearch: { classPropertyName: "presetSearch", publicName: "presetSearch", isSignal: true, isRequired: false, transformFunction: null }, enableTimeSelection: { classPropertyName: "enableTimeSelection", publicName: "enableTimeSelection", isSignal: true, isRequired: false, transformFunction: null }, basicMode: { classPropertyName: "basicMode", publicName: "basicMode", isSignal: true, isRequired: false, transformFunction: null }, reverseInputFields: { classPropertyName: "reverseInputFields", publicName: "reverseInputFields", isSignal: true, isRequired: false, transformFunction: null }, showApplyButton: { classPropertyName: "showApplyButton", publicName: "showApplyButton", isSignal: true, isRequired: false, transformFunction: null }, hideAdvancedMode: { classPropertyName: "hideAdvancedMode", publicName: "hideAdvancedMode", isSignal: true, isRequired: false, transformFunction: null }, refLabel: { classPropertyName: "refLabel", publicName: "refLabel", isSignal: true, isRequired: false, transformFunction: null }, fromLabel: { classPropertyName: "fromLabel", publicName: "fromLabel", isSignal: true, isRequired: false, transformFunction: null }, toLabel: { classPropertyName: "toLabel", publicName: "toLabel", isSignal: true, isRequired: false, transformFunction: null }, rangeLabel: { classPropertyName: "rangeLabel", publicName: "rangeLabel", isSignal: true, isRequired: false, transformFunction: null }, todayLabel: { classPropertyName: "todayLabel", publicName: "todayLabel", isSignal: true, isRequired: false, transformFunction: null }, nowLabel: { classPropertyName: "nowLabel", publicName: "nowLabel", isSignal: true, isRequired: false, transformFunction: null }, dateLabel: { classPropertyName: "dateLabel", publicName: "dateLabel", isSignal: true, isRequired: false, transformFunction: null }, previewLabel: { classPropertyName: "previewLabel", publicName: "previewLabel", isSignal: true, isRequired: false, transformFunction: null }, datePlaceholder: { classPropertyName: "datePlaceholder", publicName: "datePlaceholder", isSignal: true, isRequired: false, transformFunction: null }, beforeLabel: { classPropertyName: "beforeLabel", publicName: "beforeLabel", isSignal: true, isRequired: false, transformFunction: null }, afterLabel: { classPropertyName: "afterLabel", publicName: "afterLabel", isSignal: true, isRequired: false, transformFunction: null }, withinLabel: { classPropertyName: "withinLabel", publicName: "withinLabel", isSignal: true, isRequired: false, transformFunction: null }, valueLabel: { classPropertyName: "valueLabel", publicName: "valueLabel", isSignal: true, isRequired: false, transformFunction: null }, unitLabel: { classPropertyName: "unitLabel", publicName: "unitLabel", isSignal: true, isRequired: false, transformFunction: null }, searchLabel: { classPropertyName: "searchLabel", publicName: "searchLabel", isSignal: true, isRequired: false, transformFunction: null }, presetLabel: { classPropertyName: "presetLabel", publicName: "presetLabel", isSignal: true, isRequired: false, transformFunction: null }, advancedLabel: { classPropertyName: "advancedLabel", publicName: "advancedLabel", isSignal: true, isRequired: false, transformFunction: null }, applyLabel: { classPropertyName: "applyLabel", publicName: "applyLabel", isSignal: true, isRequired: false, transformFunction: null }, datepickerConfig: { classPropertyName: "datepickerConfig", publicName: "datepickerConfig", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { range: "rangeChange", applyClicked: "applyClicked" }, host: { properties: { "class.mobile": "smallScreen" } }, usesOnChanges: true, ngImport: i0, template: "@if (presetList()?.length) {\n  @if (this.smallScreen) {\n    <div class=\"presets d-flex\">\n      <button\n        #presetTrigger=\"cdkOverlayOrigin\"\n        type=\"button\"\n        class=\"btn btn-tertiary dropdown-toggle m-5 flex-grow-1\"\n        cdkOverlayOrigin\n        [class.show]=\"presetOpen()\"\n        [attr.aria-expanded]=\"presetOpen()\"\n        (click)=\"presetOpen.set(true)\"\n      >\n        {{ presetLabel() | translate }}\n        <si-icon class=\"dropdown-caret icon\" [icon]=\"icons.elementDown2\" />\n      </button>\n      <ng-template\n        cdkConnectedOverlay\n        cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n        cdkConnectedOverlayHasBackdrop\n        [cdkConnectedOverlayOpen]=\"presetOpen()\"\n        [cdkConnectedOverlayOrigin]=\"presetTrigger\"\n        [cdkConnectedOverlayMinWidth]=\"\n          presetTrigger.elementRef.nativeElement?.getBoundingClientRect().width\n        \"\n        (backdropClick)=\"presetOpen.set(false)\"\n        (detach)=\"presetOpen.set(false)\"\n      >\n        <div\n          cdkTrapFocus\n          class=\"preset-select mobile elevation-2 rounded-2 w-100\"\n          cdkTrapFocusAutoCapture\n        >\n          <ng-container *ngTemplateOutlet=\"presets\" />\n        </div>\n      </ng-template>\n    </div>\n  } @else {\n    <div class=\"preset-select border-end\">\n      <ng-container *ngTemplateOutlet=\"presets\" />\n    </div>\n  }\n}\n<form class=\"main-form d-flex flex-column flex-fill\">\n  @if (advancedMode() || inputMode()) {\n    <div class=\"advanced-form px-6 py-4\">\n      @if (!reverseInputFields()) {\n        <ng-container *ngTemplateOutlet=\"formReferencePoint\" />\n      }\n\n      <div class=\"mb-8\">\n        @if (point2Mode() === 'date') {\n          <ng-container *ngTemplateOutlet=\"formPoint2Date\" />\n        } @else if (point2Mode() === 'duration') {\n          <ng-container *ngTemplateOutlet=\"formPoint2Duration\" />\n        }\n      </div>\n\n      @if (reverseInputFields()) {\n        <ng-container *ngTemplateOutlet=\"formReferencePoint\" />\n      }\n    </div>\n  } @else {\n    <si-datepicker\n      [config]=\"dateRangeConfig()\"\n      [focusedDate]=\"focusedDate()\"\n      [dateRange]=\"dateRange()\"\n      (dateRangeChange)=\"updateFromDateRange($event)\"\n    />\n  }\n\n  @if (advancedMode() || !hideAdvancedMode()) {\n    <label class=\"form-switch form-check ms-6\">\n      <input\n        type=\"checkbox\"\n        class=\"form-check-input\"\n        name=\"advancedMode\"\n        role=\"switch\"\n        [(ngModel)]=\"advancedMode\"\n        (ngModelChange)=\"updateOnModeChange()\"\n      />\n      <span class=\"form-check-label\">{{ advancedLabel() | translate }}</span>\n    </label>\n  }\n\n  <div class=\"mt-4 mb-6 ms-6\">\n    {{ previewLabel() | translate }}:\n    <span class=\"preview\">\n      @if (calculatedRange().valid) {\n        {{ calculatedRange().start | date: pipeFormat() }} -\n        {{ calculatedRange().end | date: pipeFormat() }}\n      } @else {\n        ?\n      }\n    </span>\n  </div>\n</form>\n\n@if (showApplyButton()) {\n  <div class=\"footer border-top px-6 py-5 d-flex\">\n    <button type=\"button\" class=\"btn btn-primary ms-auto\" (click)=\"applyClicked.emit()\">\n      {{ applyLabel() | translate }}\n    </button>\n  </div>\n}\n<ng-template #presets>\n  @if (presetSearch()) {\n    <si-search-bar\n      colorVariant=\"base-0\"\n      class=\"mx-6 mt-5 mb-6\"\n      [placeholder]=\"searchLabel() | translate\"\n      [showIcon]=\"true\"\n      [(ngModel)]=\"presetFilter\"\n    />\n  }\n  <ul class=\"overflow-auto\" cdkListbox [attr.aria-label]=\"presetLabel() | translate\">\n    @for (item of filteredPresetList(); track $index) {\n      @if (item.label | translate | presetMatchFilter: presetFilter()) {\n        <li\n          class=\"preset-item focus-inside px-8 py-5\"\n          [cdkOption]=\"item.label\"\n          (click)=\"selectPresetItem($event, item)\"\n          (keydown.enter)=\"selectPresetItem($event, item)\"\n        >\n          {{ item.label | translate }}\n        </li>\n      }\n    }\n  </ul>\n</ng-template>\n<ng-template #formReferencePoint>\n  <div class=\"mb-8\">\n    <label class=\"d-block\">\n      <span class=\"form-label\">{{\n        (advancedMode() ? refLabel() : reverseInputFields() ? toLabel() : fromLabel()) | translate\n      }}</span>\n      <si-calendar-button class=\"w-100\">\n        <input\n          type=\"text\"\n          class=\"form-control\"\n          name=\"point1\"\n          required\n          siDatepicker\n          [siDatepickerConfig]=\"datepickerConfigInternal()\"\n          [disabled]=\"point1Now()\"\n          [placeholder]=\"datePlaceholder() | translate\"\n          [(ngModel)]=\"point1date\"\n          (ngModelChange)=\"point1Changed()\"\n        />\n      </si-calendar-button>\n    </label>\n    <label class=\"ms-4 mt-4 text-nowrap form-check\">\n      <input\n        type=\"checkbox\"\n        class=\"form-check-input\"\n        name=\"point1now\"\n        [(ngModel)]=\"point1Now\"\n        (ngModelChange)=\"point1Changed()\"\n      />\n      <span class=\"form-check-label\">{{\n        (enableTimeSelection() ? nowLabel() : todayLabel()) | translate\n      }}</span>\n    </label>\n  </div>\n</ng-template>\n\n<ng-template #formPoint2Date>\n  <label class=\"d-block mb-4 bp-9\">\n    <span class=\"form-label\">{{\n      (reverseInputFields() ? fromLabel() : toLabel()) | translate\n    }}</span>\n    <si-calendar-button class=\"w-100\">\n      <input\n        type=\"text\"\n        class=\"form-control\"\n        name=\"point2\"\n        required\n        siDatepicker\n        [siDatepickerConfig]=\"datepickerConfigInternal()\"\n        [attr.aria-label]=\"dateLabel() | translate\"\n        [placeholder]=\"datePlaceholder() | translate\"\n        [(ngModel)]=\"point2date\"\n        (ngModelChange)=\"point2Changed()\"\n      />\n    </si-calendar-button>\n  </label>\n</ng-template>\n\n<ng-template #formPoint2Duration>\n  <div>\n    <span class=\"form-label\">{{ rangeLabel() | translate }}</span>\n    <si-relative-date\n      class=\"d-block mb-4\"\n      [unitLabel]=\"unitLabel() | translate\"\n      [valueLabel]=\"valueLabel() | translate\"\n      [enableTimeSelection]=\"enableTimeSelection()\"\n      [(value)]=\"point2offset\"\n      (valueChange)=\"point2Changed()\"\n    />\n    <div class=\"range-type ms-4\">\n      <label class=\"form-check form-check-inline\">\n        <input\n          type=\"radio\"\n          class=\"form-check-input\"\n          value=\"before\"\n          name=\"point2range\"\n          [(ngModel)]=\"point2range\"\n          (ngModelChange)=\"point2Changed()\"\n        />\n        <span class=\"form-check-label\">\n          {{ beforeLabel() | translate }}\n        </span>\n      </label>\n      <label class=\"form-check form-check-inline\">\n        <input\n          type=\"radio\"\n          class=\"form-check-input\"\n          value=\"after\"\n          name=\"point2range\"\n          [(ngModel)]=\"point2range\"\n          (ngModelChange)=\"point2Changed()\"\n        />\n        <span class=\"form-check-label\">\n          {{ afterLabel() | translate }}\n        </span>\n      </label>\n      <label class=\"form-check form-check-inline\">\n        <input\n          type=\"radio\"\n          class=\"form-check-input\"\n          value=\"within\"\n          name=\"point2range\"\n          [(ngModel)]=\"point2range\"\n          (ngModelChange)=\"point2Changed()\"\n        />\n        <span class=\"form-check-label\">\n          {{ withinLabel() | translate }}\n        </span>\n      </label>\n    </div>\n  </div>\n</ng-template>\n", styles: [":host{display:inline-grid;background:var(--element-base-1);grid-template-areas:\"preset main\" \"footer footer\"}:host.mobile{grid-template-areas:\"preset\" \"main\" \"footer\";justify-items:stretch}:host.mobile .presets{border-block-end:1px solid var(--element-ui-4)}.main-form{inline-size:348px;grid-area:main}.advanced-form{block-size:392px}.preset-select{display:flex;inline-size:200px;flex-direction:column;grid-area:preset;background:var(--element-base-1)}.preset-select.mobile{max-block-size:346px;inline-size:unset}ul{flex:1 1 auto;padding-inline-start:0;list-style:none}.preset-item{cursor:pointer;line-height:1.1428571429}.preset-item:hover{background:var(--element-base-1-hover)}.form-check-input{inset-block-start:0}.element-zoom{rotate:45deg}.footer{grid-area:footer}\n"], dependencies: [{ kind: "directive", type: CdkOption, selector: "[cdkOption]", inputs: ["id", "cdkOption", "cdkOptionTypeaheadLabel", "cdkOptionDisabled", "tabindex"], exportAs: ["cdkOption"] }, { kind: "directive", type: CdkListbox, selector: "[cdkListbox]", inputs: ["id", "tabindex", "cdkListboxValue", "cdkListboxMultiple", "cdkListboxDisabled", "cdkListboxUseActiveDescendant", "cdkListboxOrientation", "cdkListboxCompareWith", "cdkListboxNavigationWrapDisabled", "cdkListboxNavigatesDisabledOptions"], outputs: ["cdkListboxValueChange"], exportAs: ["cdkListbox"] }, { kind: "directive", type: CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]):not([formArray]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i2.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i2.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: SiCalendarButtonComponent, selector: "si-calendar-button", inputs: ["ariaLabel"] }, { kind: "component", type: SiDatepickerComponent, selector: "si-datepicker", inputs: ["focusedDate", "date", "dateRange", "dateRangeRole", "initialFocus", "disabledTime", "config", "previousLabel", "nextLabel", "calenderWeekLabel", "calendarWeekLabel", "time12h", "rangeType", "minMonth", "maxMonth", "hideTimeToggle", "hideCalendar", "timepickerLabel", "activeHover"], outputs: ["focusedDateChange", "dateChange", "dateRangeChange", "disabledTimeChange", "configChange", "rangeTypeChange", "activeHoverChange"] }, { kind: "directive", type: SiDatepickerDirective, selector: "[siDatepicker]", inputs: ["autoClose"], exportAs: ["siDatepicker"] }, { kind: "component", type: SiIconComponent, selector: "si-icon", inputs: ["icon"] }, { kind: "component", type: SiRelativeDateComponent, selector: "si-relative-date", inputs: ["value", "enableTimeSelection", "valueLabel", "unitLabel"], outputs: ["valueChange"] }, { kind: "component", type: SiSearchBarComponent, selector: "si-search-bar", inputs: ["debounceTime", "prohibitedCharacters", "placeholder", "showIcon", "tabbable", "value", "readonly", "colorVariant", "disabled", "clearButtonAriaLabel"], outputs: ["searchChange"] }, { kind: "pipe", type: DatePipe, name: "date" }, { kind: "pipe", type: PresetMatchFilterPipe, name: "presetMatchFilter" }, { kind: "pipe", type: SiTranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiDateRangeFilterComponent, decorators: [{
            type: Component,
            args: [{ selector: 'si-date-range-filter', imports: [
                        CdkOption,
                        CdkListbox,
                        CdkTrapFocus,
                        DatePipe,
                        FormsModule,
                        NgTemplateOutlet,
                        OverlayModule,
                        PresetMatchFilterPipe,
                        SiCalendarButtonComponent,
                        SiDatepickerComponent,
                        SiDatepickerDirective,
                        SiIconComponent,
                        SiRelativeDateComponent,
                        SiSearchBarComponent,
                        SiTranslatePipe
                    ], changeDetection: ChangeDetectionStrategy.OnPush, host: {
                        '[class.mobile]': 'smallScreen'
                    }, template: "@if (presetList()?.length) {\n  @if (this.smallScreen) {\n    <div class=\"presets d-flex\">\n      <button\n        #presetTrigger=\"cdkOverlayOrigin\"\n        type=\"button\"\n        class=\"btn btn-tertiary dropdown-toggle m-5 flex-grow-1\"\n        cdkOverlayOrigin\n        [class.show]=\"presetOpen()\"\n        [attr.aria-expanded]=\"presetOpen()\"\n        (click)=\"presetOpen.set(true)\"\n      >\n        {{ presetLabel() | translate }}\n        <si-icon class=\"dropdown-caret icon\" [icon]=\"icons.elementDown2\" />\n      </button>\n      <ng-template\n        cdkConnectedOverlay\n        cdkConnectedOverlayBackdropClass=\"cdk-overlay-transparent-backdrop\"\n        cdkConnectedOverlayHasBackdrop\n        [cdkConnectedOverlayOpen]=\"presetOpen()\"\n        [cdkConnectedOverlayOrigin]=\"presetTrigger\"\n        [cdkConnectedOverlayMinWidth]=\"\n          presetTrigger.elementRef.nativeElement?.getBoundingClientRect().width\n        \"\n        (backdropClick)=\"presetOpen.set(false)\"\n        (detach)=\"presetOpen.set(false)\"\n      >\n        <div\n          cdkTrapFocus\n          class=\"preset-select mobile elevation-2 rounded-2 w-100\"\n          cdkTrapFocusAutoCapture\n        >\n          <ng-container *ngTemplateOutlet=\"presets\" />\n        </div>\n      </ng-template>\n    </div>\n  } @else {\n    <div class=\"preset-select border-end\">\n      <ng-container *ngTemplateOutlet=\"presets\" />\n    </div>\n  }\n}\n<form class=\"main-form d-flex flex-column flex-fill\">\n  @if (advancedMode() || inputMode()) {\n    <div class=\"advanced-form px-6 py-4\">\n      @if (!reverseInputFields()) {\n        <ng-container *ngTemplateOutlet=\"formReferencePoint\" />\n      }\n\n      <div class=\"mb-8\">\n        @if (point2Mode() === 'date') {\n          <ng-container *ngTemplateOutlet=\"formPoint2Date\" />\n        } @else if (point2Mode() === 'duration') {\n          <ng-container *ngTemplateOutlet=\"formPoint2Duration\" />\n        }\n      </div>\n\n      @if (reverseInputFields()) {\n        <ng-container *ngTemplateOutlet=\"formReferencePoint\" />\n      }\n    </div>\n  } @else {\n    <si-datepicker\n      [config]=\"dateRangeConfig()\"\n      [focusedDate]=\"focusedDate()\"\n      [dateRange]=\"dateRange()\"\n      (dateRangeChange)=\"updateFromDateRange($event)\"\n    />\n  }\n\n  @if (advancedMode() || !hideAdvancedMode()) {\n    <label class=\"form-switch form-check ms-6\">\n      <input\n        type=\"checkbox\"\n        class=\"form-check-input\"\n        name=\"advancedMode\"\n        role=\"switch\"\n        [(ngModel)]=\"advancedMode\"\n        (ngModelChange)=\"updateOnModeChange()\"\n      />\n      <span class=\"form-check-label\">{{ advancedLabel() | translate }}</span>\n    </label>\n  }\n\n  <div class=\"mt-4 mb-6 ms-6\">\n    {{ previewLabel() | translate }}:\n    <span class=\"preview\">\n      @if (calculatedRange().valid) {\n        {{ calculatedRange().start | date: pipeFormat() }} -\n        {{ calculatedRange().end | date: pipeFormat() }}\n      } @else {\n        ?\n      }\n    </span>\n  </div>\n</form>\n\n@if (showApplyButton()) {\n  <div class=\"footer border-top px-6 py-5 d-flex\">\n    <button type=\"button\" class=\"btn btn-primary ms-auto\" (click)=\"applyClicked.emit()\">\n      {{ applyLabel() | translate }}\n    </button>\n  </div>\n}\n<ng-template #presets>\n  @if (presetSearch()) {\n    <si-search-bar\n      colorVariant=\"base-0\"\n      class=\"mx-6 mt-5 mb-6\"\n      [placeholder]=\"searchLabel() | translate\"\n      [showIcon]=\"true\"\n      [(ngModel)]=\"presetFilter\"\n    />\n  }\n  <ul class=\"overflow-auto\" cdkListbox [attr.aria-label]=\"presetLabel() | translate\">\n    @for (item of filteredPresetList(); track $index) {\n      @if (item.label | translate | presetMatchFilter: presetFilter()) {\n        <li\n          class=\"preset-item focus-inside px-8 py-5\"\n          [cdkOption]=\"item.label\"\n          (click)=\"selectPresetItem($event, item)\"\n          (keydown.enter)=\"selectPresetItem($event, item)\"\n        >\n          {{ item.label | translate }}\n        </li>\n      }\n    }\n  </ul>\n</ng-template>\n<ng-template #formReferencePoint>\n  <div class=\"mb-8\">\n    <label class=\"d-block\">\n      <span class=\"form-label\">{{\n        (advancedMode() ? refLabel() : reverseInputFields() ? toLabel() : fromLabel()) | translate\n      }}</span>\n      <si-calendar-button class=\"w-100\">\n        <input\n          type=\"text\"\n          class=\"form-control\"\n          name=\"point1\"\n          required\n          siDatepicker\n          [siDatepickerConfig]=\"datepickerConfigInternal()\"\n          [disabled]=\"point1Now()\"\n          [placeholder]=\"datePlaceholder() | translate\"\n          [(ngModel)]=\"point1date\"\n          (ngModelChange)=\"point1Changed()\"\n        />\n      </si-calendar-button>\n    </label>\n    <label class=\"ms-4 mt-4 text-nowrap form-check\">\n      <input\n        type=\"checkbox\"\n        class=\"form-check-input\"\n        name=\"point1now\"\n        [(ngModel)]=\"point1Now\"\n        (ngModelChange)=\"point1Changed()\"\n      />\n      <span class=\"form-check-label\">{{\n        (enableTimeSelection() ? nowLabel() : todayLabel()) | translate\n      }}</span>\n    </label>\n  </div>\n</ng-template>\n\n<ng-template #formPoint2Date>\n  <label class=\"d-block mb-4 bp-9\">\n    <span class=\"form-label\">{{\n      (reverseInputFields() ? fromLabel() : toLabel()) | translate\n    }}</span>\n    <si-calendar-button class=\"w-100\">\n      <input\n        type=\"text\"\n        class=\"form-control\"\n        name=\"point2\"\n        required\n        siDatepicker\n        [siDatepickerConfig]=\"datepickerConfigInternal()\"\n        [attr.aria-label]=\"dateLabel() | translate\"\n        [placeholder]=\"datePlaceholder() | translate\"\n        [(ngModel)]=\"point2date\"\n        (ngModelChange)=\"point2Changed()\"\n      />\n    </si-calendar-button>\n  </label>\n</ng-template>\n\n<ng-template #formPoint2Duration>\n  <div>\n    <span class=\"form-label\">{{ rangeLabel() | translate }}</span>\n    <si-relative-date\n      class=\"d-block mb-4\"\n      [unitLabel]=\"unitLabel() | translate\"\n      [valueLabel]=\"valueLabel() | translate\"\n      [enableTimeSelection]=\"enableTimeSelection()\"\n      [(value)]=\"point2offset\"\n      (valueChange)=\"point2Changed()\"\n    />\n    <div class=\"range-type ms-4\">\n      <label class=\"form-check form-check-inline\">\n        <input\n          type=\"radio\"\n          class=\"form-check-input\"\n          value=\"before\"\n          name=\"point2range\"\n          [(ngModel)]=\"point2range\"\n          (ngModelChange)=\"point2Changed()\"\n        />\n        <span class=\"form-check-label\">\n          {{ beforeLabel() | translate }}\n        </span>\n      </label>\n      <label class=\"form-check form-check-inline\">\n        <input\n          type=\"radio\"\n          class=\"form-check-input\"\n          value=\"after\"\n          name=\"point2range\"\n          [(ngModel)]=\"point2range\"\n          (ngModelChange)=\"point2Changed()\"\n        />\n        <span class=\"form-check-label\">\n          {{ afterLabel() | translate }}\n        </span>\n      </label>\n      <label class=\"form-check form-check-inline\">\n        <input\n          type=\"radio\"\n          class=\"form-check-input\"\n          value=\"within\"\n          name=\"point2range\"\n          [(ngModel)]=\"point2range\"\n          (ngModelChange)=\"point2Changed()\"\n        />\n        <span class=\"form-check-label\">\n          {{ withinLabel() | translate }}\n        </span>\n      </label>\n    </div>\n  </div>\n</ng-template>\n", styles: [":host{display:inline-grid;background:var(--element-base-1);grid-template-areas:\"preset main\" \"footer footer\"}:host.mobile{grid-template-areas:\"preset\" \"main\" \"footer\";justify-items:stretch}:host.mobile .presets{border-block-end:1px solid var(--element-ui-4)}.main-form{inline-size:348px;grid-area:main}.advanced-form{block-size:392px}.preset-select{display:flex;inline-size:200px;flex-direction:column;grid-area:preset;background:var(--element-base-1)}.preset-select.mobile{max-block-size:346px;inline-size:unset}ul{flex:1 1 auto;padding-inline-start:0;list-style:none}.preset-item{cursor:pointer;line-height:1.1428571429}.preset-item:hover{background:var(--element-base-1-hover)}.form-check-input{inset-block-start:0}.element-zoom{rotate:45deg}.footer{grid-area:footer}\n"] }]
        }], propDecorators: { range: [{ type: i0.Input, args: [{ isSignal: true, alias: "range", required: true }] }, { type: i0.Output, args: ["rangeChange"] }], presetList: [{ type: i0.Input, args: [{ isSignal: true, alias: "presetList", required: false }] }], presetSearch: [{ type: i0.Input, args: [{ isSignal: true, alias: "presetSearch", required: false }] }], enableTimeSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableTimeSelection", required: false }] }], basicMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "basicMode", required: false }] }], reverseInputFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "reverseInputFields", required: false }] }], showApplyButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showApplyButton", required: false }] }], hideAdvancedMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideAdvancedMode", required: false }] }], refLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "refLabel", required: false }] }], fromLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "fromLabel", required: false }] }], toLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "toLabel", required: false }] }], rangeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "rangeLabel", required: false }] }], todayLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "todayLabel", required: false }] }], nowLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "nowLabel", required: false }] }], dateLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateLabel", required: false }] }], previewLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previewLabel", required: false }] }], datePlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "datePlaceholder", required: false }] }], beforeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "beforeLabel", required: false }] }], afterLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "afterLabel", required: false }] }], withinLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "withinLabel", required: false }] }], valueLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueLabel", required: false }] }], unitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "unitLabel", required: false }] }], searchLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchLabel", required: false }] }], presetLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "presetLabel", required: false }] }], advancedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "advancedLabel", required: false }] }], applyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "applyLabel", required: false }] }], applyClicked: [{ type: i0.Output, args: ["applyClicked"] }], datepickerConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "datepickerConfig", required: false }] }] } });

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */
class SiDateRangeFilterModule {
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiDateRangeFilterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
    static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.0.8", ngImport: i0, type: SiDateRangeFilterModule, imports: [SiDateRangeFilterComponent], exports: [SiDateRangeFilterComponent] });
    static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiDateRangeFilterModule, imports: [SiDateRangeFilterComponent] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.8", ngImport: i0, type: SiDateRangeFilterModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [SiDateRangeFilterComponent],
                    exports: [SiDateRangeFilterComponent]
                }]
        }] });

/**
 * Copyright (c) Siemens 2016 - 2026
 * SPDX-License-Identifier: MIT
 */

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

export { ONE_DAY, ONE_MINUTE, PresetMatchFilterPipe, SiDateRangeCalculationService, SiDateRangeFilterComponent, SiDateRangeFilterModule };
//# sourceMappingURL=siemens-element-ng-date-range-filter.mjs.map
