diff --git a/package-lock.json b/package-lock.json index b6bf317728..ec622e1229 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28583,6 +28583,7 @@ "@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/react-fontawesome": "^0.2.0", "@react-spectrum/theme-default": "^3.5.1", + "@react-types/shared": "^3.22.1", "bootstrap": "4.6.2", "classnames": "^2.3.1", "event-target-shim": "^6.0.2", @@ -31032,6 +31033,7 @@ "@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/react-fontawesome": "^0.2.0", "@react-spectrum/theme-default": "^3.5.1", + "@react-types/shared": "^3.22.1", "bootstrap": "4.6.2", "classnames": "^2.3.1", "event-target-shim": "^6.0.2", diff --git a/packages/code-studio/src/styleguide/Pickers.tsx b/packages/code-studio/src/styleguide/Pickers.tsx index e698c57555..6170ec79da 100644 --- a/packages/code-studio/src/styleguide/Pickers.tsx +++ b/packages/code-studio/src/styleguide/Pickers.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import { Picker } from '@deephaven/components'; +import { Item, Picker, Section } from '@deephaven/components'; import { vsPerson } from '@deephaven/icons'; -import { Flex, Icon, Item, Text } from '@adobe/react-spectrum'; +import { Flex, Icon, Text } from '@adobe/react-spectrum'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { sampleSectionIdAndClasses } from './utils'; @@ -40,9 +40,32 @@ export function Pickers(): JSX.Element { Item Bbb - Complex Ccc + Complex Ccc with text that should be truncated + + + {/* eslint-disable react/jsx-curly-brace-presence */} + {'String 1'} + {'String 2'} + {'String 3'} +
+ Item Aaa + Item Bbb + + + Complex Ccc + +
+
+ Item Ddd + Item Eee + + + Complex Fff + +
+
); diff --git a/packages/components/package.json b/packages/components/package.json index 428e02001e..12193bcabb 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -25,6 +25,7 @@ }, "dependencies": { "@adobe/react-spectrum": "^3.34.1", + "@react-types/shared": "^3.22.1", "@deephaven/icons": "file:../icons", "@deephaven/log": "file:../log", "@deephaven/react-hooks": "file:../react-hooks", diff --git a/packages/components/src/spectrum/Item.tsx b/packages/components/src/spectrum/Item.tsx new file mode 100644 index 0000000000..a9371db928 --- /dev/null +++ b/packages/components/src/spectrum/Item.tsx @@ -0,0 +1,13 @@ +/** + * Wrapping Spectrum `Item` components will break functionality due to the way + * they are consumed by collection components. They are only used to pass data + * and don't render anything on their own, so they don't need to be wrapped. + * See https://github.com/adobe/react-spectrum/blob/main/packages/%40react-stately/collections/src/Item.ts#L17 + */ +import { Item } from '@adobe/react-spectrum'; + +export type { ItemProps } from '@react-types/shared'; + +export { Item }; + +export default Item; diff --git a/packages/components/src/spectrum/Section.tsx b/packages/components/src/spectrum/Section.tsx new file mode 100644 index 0000000000..d8b89f24af --- /dev/null +++ b/packages/components/src/spectrum/Section.tsx @@ -0,0 +1,13 @@ +/** + * Wrapping Spectrum `Section` components will break functionality due to the way + * they are consumed by collection components. They are only used to pass data + * and don't render anything on their own, so they don't need to be wrapped. + * See https://github.com/adobe/react-spectrum/blob/main/packages/%40react-stately/collections/src/Section.ts#L18 + */ +import { Section } from '@adobe/react-spectrum'; + +export type { SectionProps } from '@react-types/shared'; + +export { Section }; + +export default Section; diff --git a/packages/components/src/spectrum/index.ts b/packages/components/src/spectrum/index.ts index aea9fbd736..ec4f31aa20 100644 --- a/packages/components/src/spectrum/index.ts +++ b/packages/components/src/spectrum/index.ts @@ -1 +1,3 @@ export * from './picker'; +export * from './Item'; +export * from './Section'; diff --git a/packages/components/src/spectrum/picker/Picker.tsx b/packages/components/src/spectrum/picker/Picker.tsx index 68345b26f4..668f9bdc8c 100644 --- a/packages/components/src/spectrum/picker/Picker.tsx +++ b/packages/components/src/spectrum/picker/Picker.tsx @@ -1,18 +1,23 @@ -import { useMemo } from 'react'; -import { Item, Picker as SpectrumPicker } from '@adobe/react-spectrum'; +import { Key, useCallback, useMemo } from 'react'; +import { Picker as SpectrumPicker } from '@adobe/react-spectrum'; +import cl from 'classnames'; import { Tooltip } from '../../popper'; import { NormalizedSpectrumPickerProps, normalizePickerItemList, normalizeTooltipOptions, - PickerItem, + PickerItemOrSection, PickerItemKey, TooltipOptions, + NormalizedPickerItem, + isNormalizedPickerSection, } from './PickerUtils'; import { PickerItemContent } from './PickerItemContent'; +import { Item } from '../Item'; +import { Section } from '../Section'; export type PickerProps = { - children: PickerItem | PickerItem[]; + children: PickerItemOrSection | PickerItemOrSection[]; /** Can be set to true or a TooltipOptions to enable item tooltips */ tooltip?: boolean | TooltipOptions; /** The currently selected key in the collection (controlled). */ @@ -54,11 +59,13 @@ export type PickerProps = { */ export function Picker({ children, - tooltip, + tooltip = true, defaultSelectedKey, selectedKey, onChange, onSelectionChange, + // eslint-disable-next-line camelcase + UNSAFE_className, ...spectrumPickerProps }: PickerProps): JSX.Element { const normalizedItems = useMemo( @@ -71,10 +78,29 @@ export function Picker({ [tooltip] ); + const renderItem = useCallback( + ({ key, content, textValue }: NormalizedPickerItem) => ( + // The `textValue` prop gets used to provide the content of `