diff --git a/example/App.tsx b/example/App.tsx index eba3ed4..0cb4b03 100644 --- a/example/App.tsx +++ b/example/App.tsx @@ -9,7 +9,15 @@ import { ShowGuesser, required, AutocompleteInput, + ReferenceInput, + SimpleForm, + TextInput, + Datagrid, + List, + TextField, + SearchInput, } from 'react-admin'; +import authProvider from './authProvider'; import { QueryClient } from 'react-query'; const queryClient = new QueryClient({ @@ -36,7 +44,7 @@ export const App = ({ dataProvider }: { dataProvider: DataProvider }) => { /> @@ -47,11 +55,18 @@ export const App = ({ dataProvider }: { dataProvider: DataProvider }) => { ); }; -import { ReferenceInput, SimpleForm, TextInput } from 'react-admin'; -import authProvider from './authProvider'; +const AuthorList = () => ( + ]}> + + + + + + +); // The default value for the title field should cause a server validation error as it's not unique -export const BookCreate = () => ( +const BookCreate = () => ( diff --git a/src/Collection.spec.ts b/src/Collection.spec.ts index 55e9017..a72e461 100644 --- a/src/Collection.spec.ts +++ b/src/Collection.spec.ts @@ -403,6 +403,14 @@ describe('Collection', () => { { id: 2, a: 'foo', b: 'bar' }, { id: 3, a: { b: 'bar' } }, ]); + expect( + collection.getAll({ filter: { q: 'hello bar' } }), + ).toEqual([ + { id: 0, a: 'Hello', b: 'world' }, + { id: 1, a: 'helloworld', b: 'bunny' }, + { id: 2, a: 'foo', b: 'bar' }, + { id: 3, a: { b: 'bar' } }, + ]); }); it('should filter by range using _gte, _gt, _lte, and _lt', () => { diff --git a/src/Collection.ts b/src/Collection.ts index 45932e5..ca9614b 100644 --- a/src/Collection.ts +++ b/src/Collection.ts @@ -441,7 +441,7 @@ function filterItems( // turn filter properties to functions const filterFunctions = Object.keys(filter).map((key) => { if (key === 'q' && typeof filter.q === 'string') { - const regex = new RegExp(filter.q, 'i'); + const regex = buildRegexSearch(filter.q); const filterWithQuery = < T2 extends CollectionItem = CollectionItem, @@ -556,3 +556,22 @@ function rangeItems( } throw new Error('Unsupported range type'); } + +function buildRegexSearch(input: string) { + // Trim the input to remove leading and trailing whitespace + const trimmedInput = input.trim(); + + // Escape special characters in the input to prevent regex injection + const escapedInput = trimmedInput.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + + // Split the input into words + const words = escapedInput.split(' '); + + // Create a regex pattern to match any of the words + const pattern = words.map((word) => `(${word})`).join('|'); + + // Create a new RegExp object with the pattern, case insensitive + const regex = new RegExp(pattern, 'i'); + + return regex; +}