diff --git a/.changeset/red-mugs-live.md b/.changeset/red-mugs-live.md
new file mode 100644
index 000000000..da8ea5b70
--- /dev/null
+++ b/.changeset/red-mugs-live.md
@@ -0,0 +1,5 @@
+---
+"@cube-dev/ui-kit": patch
+---
+
+Fix FilterListBox filtering bug.
diff --git a/src/components/fields/FilterListBox/FilterListBox.tsx b/src/components/fields/FilterListBox/FilterListBox.tsx
index cdf14920f..88a1e6655 100644
--- a/src/components/fields/FilterListBox/FilterListBox.tsx
+++ b/src/components/fields/FilterListBox/FilterListBox.tsx
@@ -27,7 +27,6 @@ import {
import { mergeProps, modAttrs, useCombinedRefs } from '../../../utils/react';
import { useFocus } from '../../../utils/react/interactions';
import { StyledHeader } from '../../actions/Menu/styled';
-import { ItemBase } from '../../content/ItemBase';
import { useFieldProps, useFormProps, wrapWithField } from '../../form';
import { CubeItemProps } from '../../Item';
import { CubeListBoxProps, ListBox } from '../ListBox/ListBox';
@@ -759,19 +758,6 @@ export const FilterListBox = forwardRef(function FilterListBox<
],
);
- const hasResults = useMemo(() => {
- if (!listStateRef.current?.collection) return !!enhancedChildren;
-
- // Collection is already filtered by React Stately, just check if it has items
- for (const node of listStateRef.current.collection) {
- if (node.type === 'item') return true;
- if (node.childNodes && [...node.childNodes].length > 0) return true;
- }
- return false;
- }, [listStateRef.current?.collection, enhancedChildren, searchValue]);
-
- const showEmptyMessage = !hasResults && searchValue.trim();
-
// Handler must be defined before we render ListBox so we can pass it.
const handleSelectionChange = (selection: any) => {
if (allowsCustomValue) {
@@ -876,55 +862,51 @@ export const FilterListBox = forwardRef(function FilterListBox<
)}
{searchInput}
- {showEmptyMessage ? (
-
- {emptyLabel !== undefined ? emptyLabel : 'No results found'}
-
- ) : (
-
- {enhancedChildren as any}
-
- )}
+
+ {enhancedChildren as any}
+
);
diff --git a/src/components/fields/ListBox/ListBox.tsx b/src/components/fields/ListBox/ListBox.tsx
index b78999581..33a1a699d 100644
--- a/src/components/fields/ListBox/ListBox.tsx
+++ b/src/components/fields/ListBox/ListBox.tsx
@@ -303,6 +303,12 @@ export interface CubeListBoxProps
* Useful for implementing search/filter functionality.
*/
filter?: (nodes: Iterable) => Iterable;
+
+ /**
+ * Label to display when the list is empty (no items available).
+ * Defaults to "No items".
+ */
+ emptyLabel?: ReactNode;
}
const PROP_STYLES = [...BASE_STYLES, ...OUTER_STYLES, ...COLOR_STYLES];
@@ -508,6 +514,7 @@ export const ListBox = forwardRef(function ListBox(
selectAllLabel,
allValueProps,
filter,
+ emptyLabel = 'No items',
form,
...otherProps
} = props;
@@ -886,110 +893,121 @@ export const ListBox = forwardRef(function ListBox(
)}
{/* Scroll container wrapper */}
-
- {shouldVirtualize
- ? rowVirtualizer.getVirtualItems().map((virtualItem) => {
- const item = itemsArray[virtualItem.index];
-
- return (
-
- );
- })
- : (() => {
- const renderedItems: ReactNode[] = [];
- let isFirstSection = true;
-
- for (const item of listState.collection) {
- if (item.type === 'section') {
- if (!isFirstSection) {
+ {listState.collection.size === 0 ? (
+
+ {emptyLabel}
+
+ ) : (
+
+ {shouldVirtualize
+ ? rowVirtualizer.getVirtualItems().map((virtualItem) => {
+ const item = itemsArray[virtualItem.index];
+
+ return (
+
+ );
+ })
+ : (() => {
+ const renderedItems: ReactNode[] = [];
+ let isFirstSection = true;
+
+ for (const item of listState.collection) {
+ if (item.type === 'section') {
+ if (!isFirstSection) {
+ renderedItems.push(
+ ,
+ );
+ }
+
renderedItems.push(
- ,
);
- }
- renderedItems.push(
- ,
- );
-
- isFirstSection = false;
- } else {
- renderedItems.push(
- ,
- );
+ isFirstSection = false;
+ } else {
+ renderedItems.push(
+ ,
+ );
+ }
}
- }
- return renderedItems;
- })()}
-
+ return renderedItems;
+ })()}
+
+ )}
{footer ? (