/** * ============================================================================ * FILTER BAR MODELS - AELLA UI INTEGRATION * ============================================================================ * * ⚠️ CRITICAL: This filter bar is integrated into Aella UI (Starlight XDR Platform) * * DO NOT MODIFY WITHOUT CONSULTING AELLA UI TEAM: * - These models are used extensively in Aella's dashboard and filtering system * - Breaking changes will cause compilation errors in Aella UI * - The AellaFilterDefinition discriminated union is the PRIMARY model * - Changes to field names, types, or structure require coordinated updates * * INTEGRATION POINTS IN AELLA UI: * - libs/dashboard/ui/src/lib/dashboard-viewer/ - Dashboard filtering * - libs/shared/ui/sc-global-filter/ - Global filter bar adapter * - libs/dashboard/utils/src/lib/field-to-filter-transformer.util.ts * - server/src/services/charts/ - Backend chart data processing * * BEFORE MAKING CHANGES: * 1. Review the integration guide in Aella UI: docs/ui-kit-filter-bar-integration-context.md * 2. Test changes in Aella UI build: npm run develop_local * 3. Coordinate with Stellar Cyber backend team for API compatibility * * ARCHITECTURE: * - Discriminated union pattern with `filterType` discriminator * - Each filter type has specific required fields (from, to, min, max, etc.) * - All filters support dual-mode: included[] AND excluded[] arrays * - Options can be static (staticOptions) or async (optionsLoader) * * ============================================================================ */ /** * Filter value types supported by the filter bar * * ⚠️ DO NOT REMOVE OR RENAME - Used by Aella UI field type mapping */ export type FilterValueType = 'checkbox' | 'date-range' | 'number-range' | 'radio' | 'number-range-slider' | 'text-input' | 'number-input' | 'toggle' | 'tree' | 'query' | 'autocomplete'; /** * ============================================================================ * "ADD FILTER" FEATURE TYPES (UI-Kit Internal Use Only) * ============================================================================ * * ⚠️ FOR AELLA UI INTEGRATION - DO NOT USE THESE TYPES * * These types power UI-Kit's internal "Add Filter" browsing feature: * - AddFilterPopoverComponent - Category/property discovery UI * - FilterPropertySelectorComponent - Filter selection interface * * AELLA UI INTEGRATION STATUS: * ❌ Does NOT use: categories input * ❌ Does NOT use: properties input * ❌ Does NOT use: AddFilterPopoverComponent * ✅ ONLY uses: filters input with AellaFilterDefinition[] * * WHY AELLA DOESN'T USE THESE: * - Aella has its own filter panel UI (sc-global-filter-panel) * - Aella creates filters from ES field mappings (field-to-filter-transformer) * - Aella uses dual-mode filtering (included[] + excluded[]) * * USE FOR AELLA UI: * - AellaFilterDefinition[] (filters input) * - No categories/properties needed * * ============================================================================ */ /** * Filter category for organizing filters into logical groups * * ✅ RECOMMENDED FOR AELLA UI - Organize 1500+ filters by category * ✅ UI-Kit Standalone: ACTIVE (used by AddFilterPopoverComponent) * * CURRENT AELLA UI STATE: * - Currently uses flat list in p-multiSelect (lines 8-22 in sc-global-filter-panel) * - All 1500+ filters in one dropdown = poor UX * * RECOMMENDED AELLA UI IMPROVEMENT: * ```typescript * // Define filter categories * const FILTER_CATEGORIES: FilterCategory[] = [ * { id: 'alert', label: 'Alert Filters', icon: 'pi pi-bell', badge: '25' }, * { id: 'network', label: 'Network Filters', icon: 'pi pi-globe', badge: '150' }, * { id: 'user', label: 'User Filters', icon: 'pi pi-user', badge: '30' }, * { id: 'system', label: 'System Fields', icon: 'pi pi-cog', badge: '50' }, * { id: 'time', label: 'Time Fields', icon: 'pi pi-clock', badge: '10' }, * { id: 'dynamic', label: 'ES Dynamic Fields', icon: 'pi pi-database', badge: '1500+' } * ]; * * // Assign category to each filter in field-to-filter-transformer * function getCategoryForField(field: string): string { * if (field.startsWith('alert_')) return 'alert'; * if (field.includes('_ip') || field.includes('port')) return 'network'; * if (field.includes('user') || field.includes('username')) return 'user'; * // ... etc * return 'dynamic'; // Default for unmapped ES fields * } * * // Update UI to use accordion with categories * * * * {{ category.label }} * * * * * * * * ``` * * BENEFITS: * - Better filter discovery (browse by category instead of searching) * - Reduced cognitive load (fewer filters per view) * - Visual hierarchy (icons + badges) * - Faster navigation (expand only relevant category) */ export interface FilterCategory { id: string; label: string; badge?: string; badgeColor?: string; icon?: string; } /** * Filter property for "Add Filter" browsing UI * * ⚠️ AELLA UI: DO NOT USE (not part of integration) * ✅ UI-Kit Standalone: ACTIVE (used by FilterPropertySelectorComponent) * * Example: "Severity" property under "Alert" category */ export interface FilterProperty { id: string; label: string; categories: FilterCategory[]; /** @deprecated Use `categories` array instead. Kept for backward compatibility. */ category?: FilterCategory; valueType: FilterValueType; dataType?: string; badge?: string; badgeColor?: string; description?: string; trackedAs?: string; example?: string; usageCount?: number; volumeLabel?: string; availableValues?: string[]; filterOptions?: FilterOption[]; optionsLoader?: FilterOptionsLoader; range?: { min: number; max: number; step?: number; }; recent?: boolean; } /** * Filter mode for single-mode filtering * * ⚠️ AELLA UI: DO NOT USE (use included[] + excluded[] arrays instead) * ✅ UI-Kit Standalone: ACTIVE (used by AddFilterPopoverComponent) * * Single-mode: filter can be EITHER include OR exclude (not both) * Dual-mode (Aella): filter supports BOTH included[] AND excluded[] arrays */ export type FilterMode = 'include' | 'exclude'; /** * Legacy single-mode filter definition * * ⚠️ AELLA UI: DO NOT USE (use AellaFilterDefinition instead) * ✅ UI-Kit Standalone: SUPPORTED (backward compatibility in FilterChipComponent) * * This represents the OLD filtering model where a filter is EITHER include OR exclude. * Aella UI requires dual-mode (both included[] and excluded[] simultaneously). * * DIFFERENCES FROM AellaFilterDefinition: * 1. Uses category/property nesting (vs. flat field) * 2. Has mode: 'include' | 'exclude' (vs. included[] + excluded[]) * 3. Has values[] array (vs. type-specific arrays) * 4. Less type-safe (no discriminated union) * * For new implementations, use AellaFilterDefinition. */ /** * Async options loader for dynamic filter options * * ⚠️ CRITICAL FOR AELLA UI: * - Used to load 1500+ Elasticsearch field mappings dynamically * - Must return FilterOption[] array * - Can be sync or async (Promise) * - DO NOT change the signature without updating Aella UI adapter */ export type FilterOptionsLoader = (field: string, context?: FilterContext) => Promise | FilterOption[]; /** * Filter option interface - represents a single selectable option * * ⚠️ CRITICAL FOR AELLA UI: * - `label`: Display text (REQUIRED) * - `value`: Actual value sent to backend (REQUIRED) * - `count`: Number of results (optional, used by Aella for ES aggregations) * - `badge`: Alternative to count, formatted string like "1.2K" (optional) * - `icon`: PrimeNG icon class like "pi pi-user" (optional) * * DO NOT REMOVE: label, value properties */ export interface FilterOption { label: string; name?: string; value: string | number | boolean; count?: number; icon?: string; badge?: string; disabled?: boolean; children?: FilterOption[]; } /** * Context passed to async options loaders * * ⚠️ USED BY AELLA UI for contextual filtering */ export interface FilterContext { entity?: { id: string; type?: string; }; timeRange?: { from: Date; to: Date; }; existingFilters?: Record; searchQuery?: string; } /** * Slider configuration for number-range-slider type * * ⚠️ USED BY AELLA UI for predefined ranges like Risk Score (0-100) */ export interface SliderConfig { min: number; max: number; step?: number; unit?: string; } /** * Tree node for hierarchical tree type filters * * ⚠️ USED BY AELLA UI for MITRE ATT&CK taxonomy */ export interface TreeNode { label: string; value: string; icon?: string; children?: TreeNode[]; selectable?: boolean; expanded?: boolean; } /** * This discriminated union is the MAIN filter model used by: * - FilterBarComponent (this UI-Kit) * - Aella UI dashboard system * - Elasticsearch query builder * * ⚠️ CRITICAL ARCHITECTURE DECISIONS: * * 1. DISCRIMINATED UNION PATTERN: * - Uses `filterType` as the discriminator * - TypeScript narrows types based on filterType * - Ensures type safety across the entire filter system * * 2. DUAL-MODE FILTERING (included[] + excluded[]): * - ALL filter types support BOTH included and excluded arrays * - This enables complex security queries: "Show Critical OR High severity, BUT NOT false positives" * - Backend maps to ES boolean queries: must/must_not clauses * * 3. FIELD-BASED (not category/property): * - Uses `field` instead of category/property for direct ES field mapping * - Simpler model, less nesting * - Direct correlation to Elasticsearch field names * * 4. OPTIONS LOADING: * - `staticOptions`: For small, predefined lists (< 100 items) * - `optionsLoader`: For large, dynamic lists (1500+ ES fields in Aella) * * ⚠️ DO NOT MODIFY without testing in Aella UI: * - Field name changes break ES query mapping * - Type changes break discriminated union narrowing * - Removing fields breaks adapter components */ /** * Base properties shared by ALL filter types * * ⚠️ REQUIRED FIELDS (cannot be removed): * - id: Unique identifier for the filter * - field: Elasticsearch field name (e.g., "severity", "src_ip.keyword") * - label: Display name for the filter * - filterType: Discriminator for type narrowing * - included: Array of included values * - excluded: Array of excluded values */ interface BaseAellaFilter { id: string; field: string; label: string; categoryId?: string; placeholder?: string; searchable?: boolean; virtualScroll?: boolean; virtualScrollItemSize?: number; tooltip?: string; icon?: string; badge?: string; disabled?: boolean; required?: boolean; } /** * Checkbox filter - Multi-select with checkboxes * * ⚠️ AELLA UI USAGE: * - Most common filter type (~80% of filters) * - Maps to ES keyword/text fields * - Example: Severity (Critical, High, Medium, Low) * * REQUIRED: filterType, included, excluded, multiSelect */ export interface CheckboxFilter extends BaseAellaFilter { filterType: 'checkbox'; included: (string | number | boolean)[]; excluded: (string | number | boolean)[]; multiSelect: true; staticOptions?: FilterOption[]; optionsLoader?: FilterOptionsLoader; } /** * Radio filter - Single-select with radio buttons * * ⚠️ AELLA UI USAGE: * - Used for mutually exclusive options * - Maps to ES keyword fields * - Example: Confidence (Confirmed, Likely, Possible) * * REQUIRED: filterType, included, excluded, multiSelect */ export interface RadioFilter extends BaseAellaFilter { filterType: 'radio'; included: (string | number | boolean)[]; excluded: (string | number | boolean)[]; multiSelect: false; staticOptions?: FilterOption[]; optionsLoader?: FilterOptionsLoader; } /** * Autocomplete filter - Async search with autocomplete * * ⚠️ AELLA UI USAGE: * - Used for large datasets (IP addresses, usernames) * - Loads options dynamically as user types * - Requires optionsLoader (not staticOptions) * * REQUIRED: filterType, included, excluded, optionsLoader */ export interface AutocompleteFilter extends BaseAellaFilter { filterType: 'autocomplete'; included: (string | number | boolean)[]; excluded: (string | number | boolean)[]; multiSelect?: boolean; optionsLoader: FilterOptionsLoader; } /** * Tree filter - Hierarchical tree selection * * ⚠️ AELLA UI USAGE: * - Used for MITRE ATT&CK taxonomy (Tactics > Techniques > Sub-techniques) * - Requires treeNodes with parent-child relationships * * REQUIRED: filterType, included, excluded, treeNodes */ export interface TreeFilter extends BaseAellaFilter { filterType: 'tree'; included: (string | number | boolean)[]; excluded: (string | number | boolean)[]; multiSelect?: boolean; treeNodes: TreeNode[]; } /** * Text input filter - Single text input field * * ⚠️ AELLA UI USAGE: * - Used for text search filters (hostname, username) * - Maps to ES text/keyword fields * * REQUIRED: filterType, included, excluded */ export interface TextInputFilter extends BaseAellaFilter { filterType: 'text-input'; included: string[]; excluded: string[]; multiSelect: false; } /** * Number input filter - Single number input field * * ⚠️ AELLA UI USAGE: * - Used for single numeric values (port, count) * - Maps to ES integer/long fields * * REQUIRED: filterType, included, excluded */ export interface NumberInputFilter extends BaseAellaFilter { filterType: 'number-input'; included: number[]; excluded: number[]; multiSelect: false; min?: number; max?: number; } /** * Toggle filter - Boolean switch (ON/OFF) * * ⚠️ AELLA UI USAGE: * - Used for boolean flags (Enabled/Disabled, Active/Inactive) * - Maps to ES boolean fields * * REQUIRED: filterType, included, excluded */ export interface ToggleFilter extends BaseAellaFilter { filterType: 'toggle'; included: boolean[]; excluded: boolean[]; multiSelect: false; } /** * Number range filter - Two number inputs (from/to) * * ⚠️ AELLA UI USAGE: * - Used for numeric ranges (Score 70-100, Port 8000-9000) * - Maps to ES long/integer/float fields * - Dynamic fields have NO min/max limits * - Predefined fields MAY have min/max constraints * * ⚠️ RANGE ENCODING (NEW MODEL): * - Ranges are encoded as [from, to] tuples within included/excluded arrays * - included: [[33, 100], 50, 75] means "33-100 OR 50 OR 75" (must query) * - excluded: [[33, 100], 50, 75] means "NOT (33-100 OR 50 OR 75)" (must_not query) * - This eliminates the need for separate from/to fields * - Position of range tuple in array doesn't matter * * REQUIRED: filterType, included, excluded */ export interface NumberRangeFilter extends BaseAellaFilter { filterType: 'number-range'; included: (number | [number, number])[]; excluded: (number | [number, number])[]; min?: number; max?: number; } /** * Number range slider filter - Slider with step configuration * * ⚠️ AELLA UI USAGE: * - Used for predefined ranges like Risk Score (0-100, step 5) * - ALWAYS has min/max/step configuration * - More visual than number-range * * ⚠️ RANGE ENCODING (NEW MODEL): * - Ranges are encoded as [from, to] tuples within included/excluded arrays * - included: [[33, 100], 50, 75] means "33-100 OR 50 OR 75" (must query) * - excluded: [[33, 100], 50, 75] means "NOT (33-100 OR 50 OR 75)" (must_not query) * - This eliminates the need for separate from/to fields * - Position of range tuple in array doesn't matter * * REQUIRED: filterType, min, max, included, excluded */ export interface NumberRangeSliderFilter extends BaseAellaFilter { filterType: 'number-range-slider'; included: (number | [number, number])[]; excluded: (number | [number, number])[]; range: SliderConfig; min: number; max: number; step?: number; } /** * Date range filter - Date range picker (from/to dates) * * ⚠️ AELLA UI USAGE: * - Used for time-based filtering (Created At, Last Modified) * - Maps to ES date fields * - Backend converts to epoch timestamps * * ⚠️ RANGE ENCODING (NEW MODEL): * - Date ranges are encoded as [from, to] tuples within included/excluded arrays * - included: [[Date1, Date2]] means "Date1 to Date2" (must query) * - excluded: [[Date1, Date2]] means "NOT (Date1 to Date2)" (must_not query) * - Dates can be Date objects or ISO strings * - This eliminates the need for separate from/to fields * * REQUIRED: filterType, included, excluded */ export interface DateRangeFilter extends BaseAellaFilter { filterType: 'date-range'; included: ([Date, Date] | [string, string])[]; excluded: ([Date, Date] | [string, string])[]; multiSelect: false; } /** * Query filter - Saved query template selector * * ⚠️ AELLA UI USAGE: * - Used for complex saved queries * - Maps to stored ES query templates * * REQUIRED: filterType, included, excluded */ export interface QueryFilter extends BaseAellaFilter { filterType: 'query'; included: string[]; excluded: string[]; multiSelect?: boolean; staticOptions?: FilterOption[]; optionsLoader?: FilterOptionsLoader; } /** * ============================================================================ * AELLA FILTER DEFINITION - PRIMARY DISCRIMINATED UNION * ============================================================================ * * ⚠️ THIS IS THE MAIN TYPE USED EVERYWHERE * * Use this type for: * - FilterBarComponent filters input * - Dashboard filter state management * - Elasticsearch query building * - Backend API contracts * * Type narrowing example: * ```typescript * function processFilter(filter: AellaFilterDefinition) { * switch (filter.filterType) { * case 'checkbox': * // TypeScript knows filter is CheckboxFilter * // Access filter.staticOptions, filter.included, filter.excluded * break; * case 'number-range': * // TypeScript knows filter is NumberRangeFilter * // Access filter.included, filter.excluded, filter.min, filter.max * break; * } * } * ``` * * ⚠️ DO NOT ADD NEW TYPES without: * 1. Adding corresponding UI component in filter-value-selector.component.ts * 2. Adding ES query mapping in Aella backend * 3. Testing with Aella UI build */ export type AellaFilterDefinition = CheckboxFilter | RadioFilter | AutocompleteFilter | TreeFilter | TextInputFilter | NumberInputFilter | ToggleFilter | NumberRangeFilter | NumberRangeSliderFilter | DateRangeFilter | QueryFilter; /** * Create a checkbox filter with defaults */ export declare function createCheckboxFilter(id: string, field: string, label: string, options?: Partial>): CheckboxFilter; /** * Create a radio filter with defaults */ export declare function createRadioFilter(id: string, field: string, label: string, options?: Partial>): RadioFilter; /** * Create an autocomplete filter with defaults */ export declare function createAutocompleteFilter(id: string, field: string, label: string, optionsLoader: FilterOptionsLoader, options?: Partial>): AutocompleteFilter; /** * Create a tree filter with defaults */ export declare function createTreeFilter(id: string, field: string, label: string, treeNodes: TreeNode[], options?: Partial>): TreeFilter; /** * Create a text input filter with defaults */ export declare function createTextInputFilter(id: string, field: string, label: string, options?: Partial>): TextInputFilter; /** * Create a number input filter with defaults */ export declare function createNumberInputFilter(id: string, field: string, label: string, options?: Partial>): NumberInputFilter; /** * Create a toggle filter with defaults */ export declare function createToggleFilter(id: string, field: string, label: string, options?: Partial>): ToggleFilter; /** * Create a number range filter with defaults * Range is encoded as [[from, to]] in included array */ export declare function createNumberRangeFilter(id: string, field: string, label: string, from: number, to: number, options?: Partial>): NumberRangeFilter; /** * Create a number range slider filter with defaults * Range is encoded as [[from, to]] in included array */ export declare function createNumberRangeSliderFilter(id: string, field: string, label: string, from: number, to: number, min: number, max: number, range: SliderConfig, options?: Partial>): NumberRangeSliderFilter; /** * Create a date range filter with defaults * Range is encoded as [[from, to]] in included array */ export declare function createDateRangeFilter(id: string, field: string, label: string, from: Date, to: Date, options?: Partial>): DateRangeFilter; /** * Create a query filter with defaults */ export declare function createQueryFilter(id: string, field: string, label: string, options?: Partial>): QueryFilter; export declare function isCheckboxFilter(filter: AellaFilterDefinition): filter is CheckboxFilter; export declare function isRadioFilter(filter: AellaFilterDefinition): filter is RadioFilter; export declare function isAutocompleteFilter(filter: AellaFilterDefinition): filter is AutocompleteFilter; export declare function isTreeFilter(filter: AellaFilterDefinition): filter is TreeFilter; export declare function isTextInputFilter(filter: AellaFilterDefinition): filter is TextInputFilter; export declare function isNumberInputFilter(filter: AellaFilterDefinition): filter is NumberInputFilter; export declare function isToggleFilter(filter: AellaFilterDefinition): filter is ToggleFilter; export declare function isNumberRangeFilter(filter: AellaFilterDefinition): filter is NumberRangeFilter; export declare function isNumberRangeSliderFilter(filter: AellaFilterDefinition): filter is NumberRangeSliderFilter; export declare function isDateRangeFilter(filter: AellaFilterDefinition): filter is DateRangeFilter; export declare function isQueryFilter(filter: AellaFilterDefinition): filter is QueryFilter; /** * Type guard to check if filter is a range-based filter (number-range or number-range-slider) * These filters encode ranges as [from, to] tuples within included/excluded arrays */ export declare function isRangeFilter(filter: AellaFilterDefinition): filter is NumberRangeFilter | NumberRangeSliderFilter | DateRangeFilter; /** * Helper to extract the first range tuple from included/excluded array * Returns the first [from, to] tuple found in the array * * NOTE: This intentionally returns only the FIRST range because: * 1. The UI validates and warns if multiple ranges exist in the same mode * 2. Elasticsearch doesn't easily support OR logic for multiple ranges in the same bool clause * 3. Use extractRanges() if you need all ranges (e.g., for validation) */ export declare function extractRange(values: any[]): [number, number] | [Date, Date] | [string, string] | null; /** * Helper to extract ALL range tuples from included/excluded array * Returns array of all [from, to] tuples found */ export declare function extractRanges(values: any[]): ([number, number] | [Date, Date] | [string, string])[]; /** * Helper to extract discrete values (non-range) from included/excluded array * Returns all values that are not [from, to] tuples */ export declare function extractDiscreteValues(values: any[]): (number | string | boolean)[]; /** * Helper to combine range tuple and discrete values into a properly typed array * This is used when preserving values from the opposite array (included/excluded) */ export declare function combineRangeAndDiscrete(rangeTuple: [number, number] | [Date, Date] | [string, string] | null, discreteValues: (number | string | boolean)[]): (number | string | boolean | [number, number] | [Date, Date] | [string, string])[]; /** * Type guard to check if filter supports multi-select */ export declare function isMultiSelectFilter(filter: AellaFilterDefinition): filter is CheckboxFilter | AutocompleteFilter | TreeFilter | QueryFilter; /** * Type guard to check if filter has options (static or loader) */ export declare function hasOptions(filter: AellaFilterDefinition): filter is CheckboxFilter | RadioFilter | AutocompleteFilter | QueryFilter; export type TranslateFn = (key: string, params?: Record) => string; export interface FilterBarLabels { chip?: { includeModeLabel?: string; excludeModeLabel?: string; editIncludedTooltip?: string; editExcludedTooltip?: string; removeTooltip?: string; toggleModeTooltip?: string; includeTooltip?: string; excludeTooltip?: string; noValuesLabel?: string; includesLabel?: string; excludesLabel?: string; }; selector?: { loadingMessage?: string; errorMessage?: string; noOptionsMessage?: string; noResultsMessage?: string; searchPlaceholder?: string; selectAllLabel?: string; applyButtonLabel?: string; cancelButtonLabel?: string; clearButtonLabel?: string; copyQueryTooltip?: string; fromLabel?: string; toLabel?: string; minLabel?: string; maxLabel?: string; startDatePlaceholder?: string; endDatePlaceholder?: string; onLabel?: string; offLabel?: string; selectedCountLabel?: (count: number) => string; }; addFilter?: { buttonLabel?: string; buttonTooltip?: string; searchPlaceholder?: string; recentLabel?: string; allFiltersLabel?: string; noFiltersMessage?: string; }; bar?: { clearAllLabel?: string; clearAllTooltip?: string; filtersLabel?: (count: number) => string; /** Shown on the overflow control when some chips are collapsed (e.g. "+3 more") */ moreFiltersLabel?: (hiddenCount: number) => string; /** Tooltip for the overflow control */ moreFiltersTooltip?: string; copyQueryLabel?: string; copyQueryTooltip?: string; }; } export declare const FILTER_BAR_TRANSLATION_KEYS: { readonly chip: { readonly includeModeLabel: "filter.chip.includeModeLabel"; readonly excludeModeLabel: "filter.chip.excludeModeLabel"; readonly editIncludedTooltip: "filter.chip.editIncludedTooltip"; readonly editExcludedTooltip: "filter.chip.editExcludedTooltip"; readonly removeTooltip: "filter.chip.removeTooltip"; readonly toggleModeTooltip: "filter.chip.toggleModeTooltip"; readonly includeTooltip: "filter.chip.includeTooltip"; readonly excludeTooltip: "filter.chip.excludeTooltip"; readonly noValuesLabel: "filter.chip.noValuesLabel"; readonly includesLabel: "filter.chip.includesLabel"; readonly excludesLabel: "filter.chip.excludesLabel"; }; readonly selector: { readonly loadingMessage: "filter.selector.loadingMessage"; readonly errorMessage: "filter.selector.errorMessage"; readonly noOptionsMessage: "filter.selector.noOptionsMessage"; readonly noResultsMessage: "filter.selector.noResultsMessage"; readonly searchPlaceholder: "filter.selector.searchPlaceholder"; readonly selectAllLabel: "filter.selector.selectAllLabel"; readonly applyButtonLabel: "filter.selector.applyButtonLabel"; readonly cancelButtonLabel: "filter.selector.cancelButtonLabel"; readonly clearButtonLabel: "filter.selector.clearButtonLabel"; readonly fromLabel: "filter.selector.fromLabel"; readonly toLabel: "filter.selector.toLabel"; readonly minLabel: "filter.selector.minLabel"; readonly maxLabel: "filter.selector.maxLabel"; readonly startDatePlaceholder: "filter.selector.startDatePlaceholder"; readonly endDatePlaceholder: "filter.selector.endDatePlaceholder"; readonly onLabel: "filter.selector.onLabel"; readonly offLabel: "filter.selector.offLabel"; readonly selectedCount: "filter.selector.selectedCount"; }; readonly addFilter: { readonly buttonLabel: "filter.addFilter.buttonLabel"; readonly buttonTooltip: "filter.addFilter.buttonTooltip"; readonly searchPlaceholder: "filter.addFilter.searchPlaceholder"; readonly recentLabel: "filter.addFilter.recentLabel"; readonly allFiltersLabel: "filter.addFilter.allFiltersLabel"; readonly noFiltersMessage: "filter.addFilter.noFiltersMessage"; }; readonly bar: { readonly clearAllLabel: "filter.bar.clearAllLabel"; readonly clearAllTooltip: "filter.bar.clearAllTooltip"; readonly filtersCount: "filter.bar.filtersCount"; readonly moreFiltersLabel: "filter.bar.moreFiltersLabel"; readonly moreFiltersTooltip: "filter.bar.moreFiltersTooltip"; }; }; export interface FilterBarConfig { labels?: FilterBarLabels; translateFn?: TranslateFn; virtualScrollItemSize?: number; maxVisibleOptions?: number; enableSearch?: boolean; searchThreshold?: number; showClearAll?: boolean; /** Max chips shown in the bar before "+N more" overflow. Default: 10 (~2 wrapped rows). Set 0 or use showFilterOverflow: false to disable. */ maxVisibleChips?: number; /** When false, all chips stay in the bar (no +N overflow). Default: true */ showFilterOverflow?: boolean; showFooter?: boolean; /** Show "Copy as Query" button in the filter bar. Default: false */ showCopyQuery?: boolean; dateFormat?: string; showTime?: boolean; storageKey?: string; } export declare function getTranslatedLabel(translateFn: TranslateFn | undefined, key: string, fallback: string, params?: Record): string; export declare function toFilterOptions(values: string[]): FilterOption[]; export {};