diff --git a/.changeset/cold-cloths-relax.md b/.changeset/cold-cloths-relax.md new file mode 100644 index 0000000..65f5e49 --- /dev/null +++ b/.changeset/cold-cloths-relax.md @@ -0,0 +1,5 @@ +--- +'@warkypublic/oranguru': patch +--- + +Fixed search and allow row selection for only rows with keys diff --git a/src/Gridler/GridlerDataGrid.tsx b/src/Gridler/GridlerDataGrid.tsx index 03e80b7..50ba325 100644 --- a/src/Gridler/GridlerDataGrid.tsx +++ b/src/Gridler/GridlerDataGrid.tsx @@ -197,7 +197,13 @@ export const GridlerDataGrid = () => { onGridSelectionChange={(selection) => { let rows = CompactSelection.empty(); const currentSelection = getState('_gridSelection'); + const keyField = getState('keyField') ?? 'id'; + const getRowBuffer = getState('getRowBuffer'); for (const r of selection.rows) { + const validRowID = getRowBuffer ? getRowBuffer(r)?.[keyField] : null; + if (!validRowID) { + continue; + } rows = rows.hasIndex(r) ? rows : rows.add(r); } if (selectMode === 'row' && selection.current?.range) { @@ -206,6 +212,10 @@ export const GridlerDataGrid = () => { y < selection.current.range.y + selection.current.range.height; y++ ) { + const validRowID = getRowBuffer ? getRowBuffer(y)?.[keyField] : null; + if (!validRowID) { + continue; + } rows = rows.hasIndex(y) ? rows : rows.add(y); } } diff --git a/src/Gridler/components/Computer.tsx b/src/Gridler/components/Computer.tsx index b10aad9..06cfc33 100644 --- a/src/Gridler/components/Computer.tsx +++ b/src/Gridler/components/Computer.tsx @@ -1,5 +1,5 @@ import { CompactSelection } from '@glideapps/glide-data-grid'; -import { useDebouncedValue } from '@mantine/hooks'; +import { useDebouncedCallback } from '@mantine/hooks'; import React, { useEffect, useRef } from 'react'; import { useGridlerStore } from './GridlerStore'; @@ -7,6 +7,7 @@ import { useGridlerStore } from './GridlerStore'; //The computer component does not need to be recalculated on every render, so we use React.memo to prevent unnecessary re-renders. export const Computer = React.memo(() => { const refFirstRun = useRef(0); + const refLastSearch = useRef(''); const refLastFilters = useRef(null); const { _glideref, @@ -49,9 +50,22 @@ export const Computer = React.memo(() => { values: s.values, })); - const debouncedSearchStr = useDebouncedValue(searchStr, 400, { - leading: true, - }); + const debouncedDoSearch = useDebouncedCallback( + (searchStr: string) => { + loadPage(0, 'all').then(() => { + getState('refreshCells')?.(); + getState('_events')?.dispatchEvent?.( + new CustomEvent('onSearched', { + detail: { search: searchStr }, + }) + ); + }); + }, + { + delay: 300, + leading: false, + } + ); useEffect(() => { const searchSelection = async () => { @@ -169,19 +183,15 @@ export const Computer = React.memo(() => { }, [columns]); useEffect(() => { - if (debouncedSearchStr === undefined || debouncedSearchStr === null) { + if (searchStr === undefined || searchStr === null) { + refLastSearch.current = ''; return; } - - loadPage(0, 'all').then(() => { - getState('refreshCells')?.(); - getState('_events')?.dispatchEvent?.( - new CustomEvent('onSearched', { - detail: { search: debouncedSearchStr }, - }) - ); - }); - }, [debouncedSearchStr]); + if (refLastSearch.current !== searchStr) { + debouncedDoSearch(searchStr); + refLastSearch.current = searchStr; + } + }, [searchStr]); useEffect(() => { if (!colSort) { diff --git a/src/Gridler/components/GridlerStore.tsx b/src/Gridler/components/GridlerStore.tsx index d9f1a83..a4549d9 100644 --- a/src/Gridler/components/GridlerStore.tsx +++ b/src/Gridler/components/GridlerStore.tsx @@ -916,7 +916,7 @@ const { Provider, useStore: useGridlerStore } = createSyncStore