docs(changeset): Fixed search and allow row selection for only rows with keys

This commit is contained in:
Hein 2025-10-30 10:42:07 +02:00
parent 0943ffc483
commit b4058f1ef3
5 changed files with 42 additions and 17 deletions

View File

@ -0,0 +1,5 @@
---
'@warkypublic/oranguru': patch
---
Fixed search and allow row selection for only rows with keys

View File

@ -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);
}
}

View File

@ -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<unknown>(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) {

View File

@ -916,7 +916,7 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
hideMenu: props.hideMenu ?? menus.hide,
scrollToRowKey: props.scrollToRowKey ?? props.selectedRowKey ?? getState('scrollToRowKey'),
showMenu: props.showMenu ?? menus.show,
total_rows: props.total_rows ?? getState('total_rows') ?? 0,
total_rows: getState('total_rows') ?? props.total_rows,
};
}
);

View File

@ -2,7 +2,7 @@ export {GlidlerAPIAdaptorForGoLangv2 } from './components/adaptors/GlidlerAPIAda
export {GlidlerFormAdaptor } from './components/adaptors/GlidlerFormAdaptor'
export {GlidlerLocalDataAdaptor } from './components/adaptors/GlidlerLocalDataAdaptor'
export * from './components/Column'
export {type GridlerProps,type GridlerState, useGridlerStore } from './components/GridlerStore'
export {type GridlerProps,type GridlerRef,type GridlerState, useGridlerStore } from './components/GridlerStore'
export { GridlerRightMenuIcon } from './components/RightMenuIcon'
export {Gridler} from './Gridler'
export * from './utils'