Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion packages/sdk/src/components/editor/select/EditorMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,28 @@ const SelectEditorMainBase: ForwardRefRenderFunction<
const filteredOptions = useMemo(() => {
if (!searchValue) return options;

return options.filter((v) => v.label.toLowerCase().includes(searchValue.toLowerCase()));
const searchLower = searchValue.toLowerCase();
const filtered = options.filter((v) => v.label.toLowerCase().includes(searchLower));

// Sort to prioritize exact matches and prefix matches
return filtered.sort((a, b) => {
const aLabelLower = a.label.toLowerCase();
const bLabelLower = b.label.toLowerCase();

// Check for exact matches first
if (aLabelLower === searchLower && bLabelLower !== searchLower) return -1;
if (bLabelLower === searchLower && aLabelLower !== searchLower) return 1;

// Check for prefix matches
const aStartsWith = aLabelLower.startsWith(searchLower);
const bStartsWith = bLabelLower.startsWith(searchLower);

if (aStartsWith && !bStartsWith) return -1;
if (bStartsWith && !aStartsWith) return 1;

// If both start with search or neither does, maintain original order
return 0;
});
Comment on lines +61 to +81
Copy link

Copilot AI Oct 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Converting each option's label to lowercase multiple times is inefficient. Consider preprocessing the lowercase labels once before filtering and sorting to avoid repeated string operations.

Suggested change
const filtered = options.filter((v) => v.label.toLowerCase().includes(searchLower));
// Sort to prioritize exact matches and prefix matches
return filtered.sort((a, b) => {
const aLabelLower = a.label.toLowerCase();
const bLabelLower = b.label.toLowerCase();
// Check for exact matches first
if (aLabelLower === searchLower && bLabelLower !== searchLower) return -1;
if (bLabelLower === searchLower && aLabelLower !== searchLower) return 1;
// Check for prefix matches
const aStartsWith = aLabelLower.startsWith(searchLower);
const bStartsWith = bLabelLower.startsWith(searchLower);
if (aStartsWith && !bStartsWith) return -1;
if (bStartsWith && !aStartsWith) return 1;
// If both start with search or neither does, maintain original order
return 0;
});
// Preprocess options to include lowercase label
const optionsWithLower = options.map((option) => ({
option,
labelLower: option.label.toLowerCase(),
}));
const filtered = optionsWithLower.filter((v) => v.labelLower.includes(searchLower));
// Sort to prioritize exact matches and prefix matches
filtered.sort((a, b) => {
// Check for exact matches first
if (a.labelLower === searchLower && b.labelLower !== searchLower) return -1;
if (b.labelLower === searchLower && a.labelLower !== searchLower) return 1;
// Check for prefix matches
const aStartsWith = a.labelLower.startsWith(searchLower);
const bStartsWith = b.labelLower.startsWith(searchLower);
if (aStartsWith && !bStartsWith) return -1;
if (bStartsWith && !aStartsWith) return 1;
// If both start with search or neither does, maintain original order
return 0;
});
// Return the original option objects
return filtered.map((v) => v.option);

Copilot uses AI. Check for mistakes.
}, [options, searchValue]);

const onSelect = (val: string) => {
Expand Down