Skip to content

Commit

Permalink
ComboBox component (deephaven#201)
Browse files Browse the repository at this point in the history
  • Loading branch information
bmingles committed Jul 5, 2024
1 parent d940b82 commit 1e4140f
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 14 deletions.
44 changes: 44 additions & 0 deletions plugins/ui/src/js/src/elements/ComboBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useSelector } from 'react-redux';
import {
ComboBox as DHComboBox,
ComboBoxProps as DHComboBoxProps,
} from '@deephaven/components';
import {
ComboBox as DHComboBoxJSApi,
ComboBoxProps as DHComboBoxJSApiProps,
} from '@deephaven/jsapi-components';
import { isElementOfType } from '@deephaven/react-hooks';
import { getSettings, RootState } from '@deephaven/redux';
import {
SerializedPickerProps,
usePickerProps,
WrappedDHPickerJSApiProps,
} from './hooks/usePickerProps';
import ObjectView from './ObjectView';
import { useReExportedTable } from './hooks/useReExportedTable';

export function ComboBox(
props: SerializedPickerProps<
DHComboBoxProps | WrappedDHPickerJSApiProps<DHComboBoxJSApiProps>
>
): JSX.Element | null {
const settings = useSelector(getSettings<RootState>);
const { children, ...pickerProps } = usePickerProps(props);

const isObjectView = isElementOfType(children, ObjectView);
const table = useReExportedTable(children);

if (isObjectView) {
return (
table && (
// eslint-disable-next-line react/jsx-props-no-spreading
<DHComboBoxJSApi {...pickerProps} table={table} settings={settings} />
)
);
}

// eslint-disable-next-line react/jsx-props-no-spreading
return <DHComboBox {...pickerProps}>{children}</DHComboBox>;
}

export default ComboBox;
22 changes: 18 additions & 4 deletions plugins/ui/src/js/src/elements/Picker.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
import { useSelector } from 'react-redux';
import { Picker as DHPicker } from '@deephaven/components';
import { Picker as DHPickerJSApi } from '@deephaven/jsapi-components';
import {
Picker as DHPicker,
PickerProps as DHPickerProps,
} from '@deephaven/components';
import {
Picker as DHPickerJSApi,
PickerProps as DHPickerJSApiProps,
} from '@deephaven/jsapi-components';
import { isElementOfType } from '@deephaven/react-hooks';
import { getSettings, RootState } from '@deephaven/redux';
import { SerializedPickerProps, usePickerProps } from './hooks/usePickerProps';
import {
SerializedPickerProps,
usePickerProps,
WrappedDHPickerJSApiProps,
} from './hooks/usePickerProps';
import ObjectView from './ObjectView';
import useReExportedTable from './hooks/useReExportedTable';

export function Picker(props: SerializedPickerProps): JSX.Element | null {
export function Picker(
props: SerializedPickerProps<
DHPickerProps | WrappedDHPickerJSApiProps<DHPickerJSApiProps>
>
): JSX.Element | null {
const settings = useSelector(getSettings<RootState>);
const { children, ...pickerProps } = usePickerProps(props);

Expand Down
36 changes: 26 additions & 10 deletions plugins/ui/src/js/src/elements/hooks/usePickerProps.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { PickerProps as DHPickerProps } from '@deephaven/components';
import { PickerProps as DHPickerJSApiProps } from '@deephaven/jsapi-components';
import { ReactElement } from 'react';
import ObjectView, { ObjectViewProps } from '../ObjectView';
import {
DeserializedFocusEventCallback,
SerializedFocusEventCallback,
useFocusEventCallback,
} from './useFocusEventCallback';
import {
DeserializedKeyboardEventCallback,
SerializedKeyboardEventCallback,
useKeyboardEventCallback,
} from './useKeyboardEventCallback';
Expand All @@ -25,28 +25,44 @@ export interface SerializedPickerEventProps {
onKeyUp?: SerializedKeyboardEventCallback;
}

type WrappedDHPickerJSApiProps = Omit<DHPickerJSApiProps, 'table'> & {
export interface DeserializedPickerEventProps {
/** Handler that is called when the element receives focus. */
onFocus?: DeserializedFocusEventCallback;

/** Handler that is called when the element loses focus. */
onBlur?: DeserializedFocusEventCallback;

/** Handler that is called when a key is pressed */
onKeyDown?: DeserializedKeyboardEventCallback;

/** Handler that is called when a key is released */
onKeyUp?: DeserializedKeyboardEventCallback;
}

export type WrappedDHPickerJSApiProps<TProps> = Omit<TProps, 'table'> & {
children: ReactElement<ObjectViewProps, typeof ObjectView>;
};

export type SerializedPickerProps = (
| DHPickerProps
| WrappedDHPickerJSApiProps
) &
SerializedPickerEventProps;
export type SerializedPickerProps<TProps> = TProps & SerializedPickerEventProps;

export type DeserializedPickerProps<TProps> = Omit<
TProps,
keyof SerializedPickerEventProps
> &
DeserializedPickerEventProps;

/**
* Wrap Picker props with the appropriate serialized event callbacks.
* @param props Props to wrap
* @returns Wrapped props
*/
export function usePickerProps({
export function usePickerProps<TProps>({
onFocus,
onBlur,
onKeyDown,
onKeyUp,
...otherProps
}: SerializedPickerProps): DHPickerProps | WrappedDHPickerJSApiProps {
}: SerializedPickerProps<TProps>): DeserializedPickerProps<TProps> {
const serializedOnFocus = useFocusEventCallback(onFocus);
const serializedOnBlur = useFocusEventCallback(onBlur);
const serializedOnKeyDown = useKeyboardEventCallback(onKeyDown);
Expand Down
1 change: 1 addition & 0 deletions plugins/ui/src/js/src/elements/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './ActionButton';
export * from './ActionGroup';
export * from './Button';
export * from './ComboBox';
export * from './Form';
export * from './hooks';
export * from './HTMLElementView';
Expand Down
1 change: 1 addition & 0 deletions plugins/ui/src/js/src/elements/model/ElementConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const ELEMENT_NAME = {
button: uiComponentName('Button'),
buttonGroup: uiComponentName('ButtonGroup'),
checkbox: uiComponentName('Checkbox'),
comboBox: uiComponentName('ComboBox'),
content: uiComponentName('Content'),
contextualHelp: uiComponentName('ContextualHelp'),
flex: uiComponentName('Flex'),
Expand Down
2 changes: 2 additions & 0 deletions plugins/ui/src/js/src/widget/WidgetUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import {
ActionButton,
ActionGroup,
Button,
ComboBox,
Form,
IllustratedMessage,
ListView,
Expand Down Expand Up @@ -97,6 +98,7 @@ export const elementComponentMap = {
[ELEMENT_NAME.button]: Button,
[ELEMENT_NAME.buttonGroup]: ButtonGroup,
[ELEMENT_NAME.checkbox]: Checkbox,
[ELEMENT_NAME.comboBox]: ComboBox,
[ELEMENT_NAME.content]: Content,
[ELEMENT_NAME.contextualHelp]: ContextualHelp,
[ELEMENT_NAME.flex]: Flex,
Expand Down

0 comments on commit 1e4140f

Please sign in to comment.