diff --git a/invokeai/frontend/web/src/common/components/Picker/Picker.tsx b/invokeai/frontend/web/src/common/components/Picker/Picker.tsx
index cdfe8d1cdc..3b48369923 100644
--- a/invokeai/frontend/web/src/common/components/Picker/Picker.tsx
+++ b/invokeai/frontend/web/src/common/components/Picker/Picker.tsx
@@ -34,6 +34,22 @@ const DefaultGroupHeaderComponent = ({ id }: { id: string }) => {
return {id};
};
+const DefaultNoOptionsFallback = () => {
+ return (
+
+ No options available
+
+ );
+};
+
+const DefaultNoMatchesFallback = () => {
+ return (
+
+ No matching options
+
+ );
+};
+
export type PickerProps = {
options: (T | Group)[];
getOptionId: (option: T) => string;
@@ -49,15 +65,21 @@ export type PickerProps = {
GroupHeaderComponent?: React.ComponentType<{ group: Group }>;
};
-export const getRegex = (searchTerm: string) =>
- new RegExp(
- searchTerm
- .trim()
- .replace(/[-[\]{}()*+!<=:?./\\^$|#,]/g, '')
- .split(' ')
- .join('.*'),
- 'gi'
- );
+export const getRegex = (searchTerm: string) => {
+ const terms = searchTerm
+ .trim()
+ .replace(/[-[\]{}()*+!<=:?./\\^$|#,]/g, '')
+ .split(' ')
+ .filter((term) => term.length > 0);
+
+ if (terms.length === 0) {
+ return new RegExp('', 'gi');
+ }
+
+ // Create positive lookaheads for each term - matches in any order
+ const pattern = terms.map((term) => `(?=.*${term})`).join('');
+ return new RegExp(`${pattern}.+`, 'i');
+};
const getFirstOption = (options: (T | Group)[]): T | undefined => {
const firstOptionOrGroup = options[0];
@@ -121,8 +143,8 @@ export const Picker = typedMemo((props: PickerProps) => {
handleRef,
isMatch,
getIsDisabled,
- noMatchesFallback,
- noOptionsFallback,
+ noMatchesFallback = ,
+ noOptionsFallback = ,
onClose,
onSelect,
selectedItem,
diff --git a/invokeai/frontend/web/src/features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion.tsx b/invokeai/frontend/web/src/features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion.tsx
index 561c03930f..738a21e742 100644
--- a/invokeai/frontend/web/src/features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion.tsx
+++ b/invokeai/frontend/web/src/features/settingsAccordions/components/GenerationSettingsAccordion/GenerationSettingsAccordion.tsx
@@ -216,12 +216,10 @@ const MainModelPicker = memo(() => {
getOptionId={getOptionId}
onSelect={onSelect}
selectedItem={modelConfig}
- getIsDisabled={getIsDisabled}
+ // getIsDisabled={getIsDisabled}
isMatch={isMatch}
OptionComponent={PickerItemComponent}
GroupHeaderComponent={PickerGroupHeaderComponent}
- noOptionsFallback={{t('common.noOptions')}}
- noMatchesFallback={{t('common.noMatches')}}
/>
@@ -233,7 +231,7 @@ MainModelPicker.displayName = 'MainModelPicker';
const PickerGroupHeaderComponent = memo(
({ group }: { group: Group }) => {
return (
-
+
{group.data.name}
@@ -276,18 +274,11 @@ const BASE_KEYWORDS: { [key in BaseModelType]?: string[] } = {
const isMatch = (model: AnyModelConfig, searchTerm: string) => {
const regex = getRegex(searchTerm);
+ const bases = BASE_KEYWORDS[model.base] ?? [model.base];
+ const testString =
+ `${model.name} ${bases.join(' ')} ${model.type} ${model.description ?? ''} ${model.format}`.toLowerCase();
- if (
- model.name.toLowerCase().includes(searchTerm) ||
- regex.test(model.name) ||
- (BASE_KEYWORDS[model.base] ?? [model.base]).some((kw) => kw.toLowerCase().includes(searchTerm) || regex.test(kw)) ||
- model.type.toLowerCase().includes(searchTerm) ||
- regex.test(model.type) ||
- (model.description ?? '').toLowerCase().includes(searchTerm) ||
- regex.test(model.description ?? '') ||
- model.format.toLowerCase().includes(searchTerm) ||
- regex.test(model.format)
- ) {
+ if (testString.includes(searchTerm) || regex.test(testString)) {
return true;
}