From f28a15f02c221238319cbadc268e3b196791c93e Mon Sep 17 00:00:00 2001 From: Brian Ingles Date: Wed, 1 May 2024 18:07:35 -0500 Subject: [PATCH] ActionGroup wrapper (#445) --- .../ui/src/js/src/elements/ActionGroup.tsx | 39 ++++++++++++++++++ ...nEventCallback.ts => useSelectionProps.ts} | 41 ++++++++++++++++++- .../src/js/src/elements/useListViewProps.ts | 40 +++++++----------- plugins/ui/src/js/src/widget/WidgetUtils.tsx | 2 +- 4 files changed, 95 insertions(+), 27 deletions(-) create mode 100644 plugins/ui/src/js/src/elements/ActionGroup.tsx rename plugins/ui/src/js/src/elements/spectrum/{useSelectionEventCallback.ts => useSelectionProps.ts} (50%) diff --git a/plugins/ui/src/js/src/elements/ActionGroup.tsx b/plugins/ui/src/js/src/elements/ActionGroup.tsx new file mode 100644 index 000000000..4b435b20c --- /dev/null +++ b/plugins/ui/src/js/src/elements/ActionGroup.tsx @@ -0,0 +1,39 @@ +import { + ActionGroup as DHActionGroup, + ActionGroupProps as DHActionGroupProps, +} from '@deephaven/components'; +import { + SerializedSelectionProps, + useSelectionProps, +} from './spectrum/useSelectionProps'; + +export type SerializedActionGroupProps = Omit< + DHActionGroupProps, + 'selectionMode' | 'onChange' | 'onSelectionChange' +> & + SerializedSelectionProps; + +function ActionGroup({ + selectionMode: selectionModeMaybeUppercase, + onChange: serializedOnChange, + onSelectionChange: serializedOnSelectionChange, + ...props +}: SerializedActionGroupProps): JSX.Element { + const { selectionMode, onChange, onSelectionChange } = useSelectionProps({ + selectionMode: selectionModeMaybeUppercase, + onChange: serializedOnChange, + onSelectionChange: serializedOnSelectionChange, + }); + + return ( + + ); +} + +export default ActionGroup; diff --git a/plugins/ui/src/js/src/elements/spectrum/useSelectionEventCallback.ts b/plugins/ui/src/js/src/elements/spectrum/useSelectionProps.ts similarity index 50% rename from plugins/ui/src/js/src/elements/spectrum/useSelectionEventCallback.ts rename to plugins/ui/src/js/src/elements/spectrum/useSelectionProps.ts index c64c95226..8f6e770ed 100644 --- a/plugins/ui/src/js/src/elements/spectrum/useSelectionEventCallback.ts +++ b/plugins/ui/src/js/src/elements/spectrum/useSelectionProps.ts @@ -1,5 +1,6 @@ -import type { ItemKey, ItemSelection } from '@deephaven/components'; import { useCallback } from 'react'; +import type { SelectionMode } from '@react-types/shared'; +import type { ItemKey, ItemSelection } from '@deephaven/components'; export type SerializedSelection = 'all' | ItemKey[]; @@ -7,6 +8,25 @@ export type SerializedSelectionEventCallback = ( event: SerializedSelection ) => void; +export interface SerializedSelectionProps { + selectionMode?: SelectionMode | Uppercase; + + /** Handler that is called when selection changes */ + onChange?: SerializedSelectionEventCallback; + + /** + * Handler that is called when the selection changes. + * @deprecated Use `onChange` instead + */ + onSelectionChange?: SerializedSelectionEventCallback; +} + +export interface SelectionProps { + selectionMode?: SelectionMode; + onChange?: (selection: ItemSelection) => void; + onSelectionChange?: (selection: ItemSelection) => void; +} + /** * Selection can be 'all' or a Set of keys. If it is a Set, serialize it as an * array. @@ -40,3 +60,22 @@ export function useSelectionEventCallback( [callback] ); } + +export function useSelectionProps({ + selectionMode, + onChange, + onSelectionChange, +}: SerializedSelectionProps): SelectionProps { + const selectionModeLc = selectionMode?.toLowerCase() as SelectionMode; + + const serializedOnChange = useSelectionEventCallback(onChange); + const serializedOnSelectionChange = + useSelectionEventCallback(onSelectionChange); + + return { + selectionMode: selectionModeLc, + onChange: onChange == null ? undefined : serializedOnChange, + onSelectionChange: + onSelectionChange == null ? undefined : serializedOnSelectionChange, + }; +} diff --git a/plugins/ui/src/js/src/elements/useListViewProps.ts b/plugins/ui/src/js/src/elements/useListViewProps.ts index b2e2e76e5..467030437 100644 --- a/plugins/ui/src/js/src/elements/useListViewProps.ts +++ b/plugins/ui/src/js/src/elements/useListViewProps.ts @@ -4,9 +4,9 @@ import { ListViewProps as DHListViewProps } from '@deephaven/components'; import { ListViewProps as DHListViewJSApiProps } from '@deephaven/jsapi-components'; import { ObjectViewProps } from './ObjectView'; import { - SerializedSelectionEventCallback, - useSelectionEventCallback, -} from './spectrum/useSelectionEventCallback'; + SerializedSelectionProps, + useSelectionProps, +} from './spectrum/useSelectionProps'; type Density = Required['density']; @@ -25,22 +25,11 @@ type WrappedDHListViewProps = Omit< selectionMode?: SelectionMode | Uppercase; }; -export interface SerializedListViewEventProps { - /** Handler that is called when selection changes */ - onChange?: SerializedSelectionEventCallback; - - /** - * Handler that is called when the selection changes. - * @deprecated Use `onChange` instead - */ - onSelectionChange?: SerializedSelectionEventCallback; -} - export type SerializedListViewProps = ( | WrappedDHListViewProps | WrappedDHListViewJSApiProps ) & - SerializedListViewEventProps; + SerializedSelectionProps; /** * Wrap ListView props with the appropriate serialized event callbacks. @@ -49,23 +38,24 @@ export type SerializedListViewProps = ( */ export function useListViewProps({ density, - selectionMode, - onChange, - onSelectionChange, + selectionMode: selectionModeMaybeUppercase, + onChange: serializedOnChange, + onSelectionChange: serializedOnSelectionChange, ...otherProps }: SerializedListViewProps): DHListViewProps | WrappedDHListViewJSApiProps { const densityLc = density?.toLowerCase() as Density; - const selectionModeLc = selectionMode?.toLowerCase() as SelectionMode; - const serializedOnChange = useSelectionEventCallback(onChange); - const serializedOnSelectionChange = - useSelectionEventCallback(onSelectionChange); + const { selectionMode, onChange, onSelectionChange } = useSelectionProps({ + selectionMode: selectionModeMaybeUppercase, + onChange: serializedOnChange, + onSelectionChange: serializedOnSelectionChange, + }); return { density: densityLc, - selectionMode: selectionModeLc, - onChange: serializedOnChange, - onSelectionChange: serializedOnSelectionChange, + selectionMode, + onChange, + onSelectionChange, // The @deephaven/components `ListView` has its own normalization logic that // handles primitive children types (string, number, boolean). It also // handles nested children inside of `Item` and `Section` components, so diff --git a/plugins/ui/src/js/src/widget/WidgetUtils.tsx b/plugins/ui/src/js/src/widget/WidgetUtils.tsx index 5ebfd2219..76c1ed142 100644 --- a/plugins/ui/src/js/src/widget/WidgetUtils.tsx +++ b/plugins/ui/src/js/src/widget/WidgetUtils.tsx @@ -4,7 +4,6 @@ import React, { ComponentType } from 'react'; // Importing `Item` and `Section` compnents directly since they should not be // wrapped due to how Spectrum collection components consume them. import { - ActionGroup, ActionMenu, Item, ListActionGroup, @@ -34,6 +33,7 @@ import Column from '../layout/Column'; import Dashboard from '../layout/Dashboard'; import ListView from '../elements/ListView'; import Picker from '../elements/Picker'; +import ActionGroup from '../elements/ActionGroup'; /* * Map element node names to their corresponding React components