diff --git a/packages/ui/src/ui/filters/filters.i18n.ts b/packages/ui/src/ui/filters/filters.i18n.ts index 948485b01d..ddb61e6e49 100644 --- a/packages/ui/src/ui/filters/filters.i18n.ts +++ b/packages/ui/src/ui/filters/filters.i18n.ts @@ -1,2 +1,5 @@ +export const CHUNKS_NOT_FOUND = 'No chunks found'; +export const CHUNKS_SEARCH = 'Search by chunk name'; +export const CHUNKS_SEARCH_CLEAR = 'Clear search'; export const CLEAR = 'Clear all'; export const CHECK = 'Check all'; diff --git a/packages/ui/src/ui/filters/filters.module.css b/packages/ui/src/ui/filters/filters.module.css index 02f68f4173..c457b1fcef 100644 --- a/packages/ui/src/ui/filters/filters.module.css +++ b/packages/ui/src/ui/filters/filters.module.css @@ -116,6 +116,35 @@ text-transform: lowercase; } +.filterGroupSearchWrapper { + padding-bottom: var(--space-xxxsmall); + margin-bottom: var(--space-xxxsmall); + border-bottom: 1px solid var(--color-outline); +} + +.filterGroupSearchNotFound { + padding: var(--space-xxsmall) 0; + text-align: center; + font-size: var(--size-small); + color: var(--color-text-light); +} + +.filterGroupSearchNotFoundClear { + outline: none; + appearance: none; + border: none; + background: none; + cursor: pointer; + white-space: nowrap; + color: var(--color-text-dark); +} + +.filterGroupSearchNotFoundClear:hover, +.filterGroupSearchNotFoundClear:active, +.filterGroupSearchNotFoundClear:focus { + color: var(--color-text-dark); +} + .filterGroupItems { max-height: calc(10 * (var(--space-small) + 2 * var(--space-xxxsmall))); overflow: auto; diff --git a/packages/ui/src/ui/filters/filters.tsx b/packages/ui/src/ui/filters/filters.tsx index 0c627daec9..a4ab80f969 100644 --- a/packages/ui/src/ui/filters/filters.tsx +++ b/packages/ui/src/ui/filters/filters.tsx @@ -1,9 +1,11 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import cx from 'classnames'; import type { FilterFieldsData, FilterGroupFieldData } from '../../types'; import { FlexStack } from '../../layout/flex-stack'; +import { Stack } from '../../layout/stack'; import { Dropdown } from '../dropdown'; +import { InputSearch } from '../input-search'; import * as I18N from './filters.i18n'; import { getGroupFiltersLabelSuffix, LABELS } from './filters.utils'; import css from './filters.module.css'; @@ -75,6 +77,8 @@ const FilterGroup = (props: FilterGroupProps) => { toggleFilters, } = props; + const [search, setSearch] = useState(''); + const { label: groupLabel, children: groupItems } = data; const areAllGroupItemsChecked = groupItems @@ -108,6 +112,14 @@ const FilterGroup = (props: FilterGroupProps) => { }); }; + const filteredGroupItems = useMemo(() => { + if (!search) { + return groupItems; + } + + return groupItems.filter((item) => item.label.match(new RegExp(`${search}`, 'i'))); + }, [search, groupItems]); + return ( { {({ MenuItem, menuItemClassName }) => { return ( <> + {groupItems.length > 10 && ( +
+ +
+ )}
- {groupItems.map(({ key: itemKey, ...itemData }) => { + {filteredGroupItems.length === 0 && ( + +

{I18N.CHUNKS_NOT_FOUND}

+
+ +
+
+ )} + {filteredGroupItems.map(({ key: itemKey, ...itemData }) => { const id = [groupKey, itemKey].join('.'); const getOnOnlyClick = () => getOnGroupCheck(false, { [id]: true }); @@ -138,29 +174,31 @@ const FilterGroup = (props: FilterGroupProps) => { ); })}
-
- {areAllGroupItemsChecked ? ( - - {I18N.CLEAR} - - ) : ( - - {I18N.CHECK} - - )} -
+ {filteredGroupItems.length !== 0 && ( +
+ {areAllGroupItemsChecked ? ( + + {I18N.CLEAR} + + ) : ( + + {I18N.CHECK} + + )} +
+ )} ); }}