/**
* ============================================================================
* 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 {};