Skip to content

Commit

Permalink
Wired up search (deephaven#2074)
Browse files Browse the repository at this point in the history
  • Loading branch information
bmingles committed Jun 25, 2024
1 parent cfc8bde commit 52ec32e
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 24 deletions.
17 changes: 16 additions & 1 deletion packages/jsapi-components/src/spectrum/ComboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
NormalizedItem,
SpectrumComboBoxProps,
} from '@deephaven/components';
import { useCallback } from 'react';
import { PickerWithTableProps } from './PickerProps';
import { usePickerProps } from './utils';

Expand All @@ -11,11 +12,25 @@ export type ComboBoxProps = PickerWithTableProps<
>;

export function ComboBox(props: ComboBoxProps): JSX.Element {
const pickerProps = usePickerProps(props);
const {
onInputChange: onInputChangeInternal,
onSearchTextChange,
...pickerProps
} = usePickerProps<ComboBoxProps>(props);

const onInputChange = useCallback(
(value: string) => {
onInputChangeInternal?.(value);
onSearchTextChange(value);
},
[onInputChangeInternal, onSearchTextChange]
);

return (
<ComboBoxNormalized
// eslint-disable-next-line react/jsx-props-no-spreading
{...pickerProps}
onInputChange={onInputChange}
/>
);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/jsapi-components/src/spectrum/Picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { PickerProps } from './PickerProps';
import { usePickerProps } from './utils';

export function Picker(props: PickerProps): JSX.Element {
const pickerProps = usePickerProps(props);
const pickerProps = usePickerProps<PickerProps>(props);

return (
<PickerNormalized
Expand Down
66 changes: 44 additions & 22 deletions packages/jsapi-components/src/spectrum/utils/usePickerProps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import {
ItemKey,
NormalizedItem,
NormalizedItemData,
NormalizedSection,
NormalizedSectionData,
usePickerItemScale,
} from '@deephaven/components';
import { dh as DhType } from '@deephaven/jsapi-types';
import { TableUtils } from '@deephaven/jsapi-utils';
import Log from '@deephaven/log';
import { usePromiseFactory } from '@deephaven/react-hooks';
import { PICKER_TOP_OFFSET } from '@deephaven/utils';
import useFormatter from '../../useFormatter';
import type { PickerWithTableProps } from '../PickerProps';
import { getItemKeyColumn } from './itemUtils';
import useItemRowDeserializer from './useItemRowDeserializer';
import useGetItemIndexByValue from '../../useGetItemIndexByValue';
import useViewportData from '../../useViewportData';
import { getItemKeyColumn, getItemLabelColumn } from './itemUtils';
import { useItemRowDeserializer } from './useItemRowDeserializer';
import { useGetItemIndexByValue } from '../../useGetItemIndexByValue';
import useSearchableViewportData from '../../useSearchableViewportData';

const log = Log.module('jsapi-components.usePickerProps');

Expand All @@ -26,6 +25,7 @@ export type UsePickerDerivedProps = {
getInitialScrollPosition: () => Promise<number | null>;
onChange: (key: ItemKey | null) => void;
onScroll: (event: Event) => void;
onSearchTextChange: (searchText: string) => void;
};

/**
Expand All @@ -49,7 +49,7 @@ export type UsePickerProps<TProps> = UsePickerDerivedProps &
UsePickerPassthroughProps<TProps>;

export function usePickerProps<TProps>({
table,
table: tableSource,
keyColumn: keyColumnName,
labelColumn: labelColumnName,
iconColumn: iconColumnName,
Expand All @@ -69,22 +69,44 @@ export function usePickerProps<TProps>({
ItemKey | null | undefined
>(props.defaultSelectedKey);

// Copy table so we can apply filters without affecting the original table.
// (Note that this call is not actually applying any filters. Filter will be
// applied in `useSearchableViewportData`.)
const { data: tableCopy } = usePromiseFactory(
TableUtils.copyTableAndApplyFilters,
[tableSource]
);

const keyColumn = useMemo(
() => getItemKeyColumn(table, keyColumnName),
[keyColumnName, table]
() =>
tableCopy == null ? null : getItemKeyColumn(tableCopy, keyColumnName),
[keyColumnName, tableCopy]
);

const labelColumn = useMemo(
() =>
tableCopy == null || keyColumn == null
? null
: getItemLabelColumn(tableCopy, keyColumn, labelColumnName),
[keyColumn, labelColumnName, tableCopy]
);

const searchColumnNames = useMemo(
() => (labelColumn == null ? [] : [labelColumn.name]),
[labelColumn]
);

const deserializeRow = useItemRowDeserializer({
table,
table: tableCopy,
iconColumnName,
keyColumnName,
labelColumnName,
formatValue,
});

const getItemIndexByValue = useGetItemIndexByValue({
table,
columnName: keyColumn.name,
table: tableCopy,
columnName: keyColumn?.name ?? null,
value: isUncontrolled ? uncontrolledSelectedKey : props.selectedKey,
});

Expand All @@ -98,15 +120,14 @@ export function usePickerProps<TProps>({
return index * itemHeight + PICKER_TOP_OFFSET;
}, [getItemIndexByValue, itemHeight]);

const { viewportData, onScroll, setViewport } = useViewportData<
NormalizedItemData | NormalizedSectionData,
DhType.Table
>({
reuseItemsOnTableResize: true,
table,
itemHeight,
deserializeRow,
});
const { onScroll, onSearchTextChange, setViewport, viewportData } =
useSearchableViewportData({
reuseItemsOnTableResize: true,
table: tableCopy,
itemHeight,
deserializeRow,
searchColumnNames,
});

const normalizedItems = viewportData.items as (
| NormalizedItem
Expand Down Expand Up @@ -158,6 +179,7 @@ export function usePickerProps<TProps>({
getInitialScrollPosition,
onChange: onSelectionChangeInternal,
onScroll,
onSearchTextChange,
};
}

Expand Down

0 comments on commit 52ec32e

Please sign in to comment.