diff --git a/plugins/ui/src/deephaven/ui/components/item.py b/plugins/ui/src/deephaven/ui/components/item.py index d0daed2e0..581544f6d 100644 --- a/plugins/ui/src/deephaven/ui/components/item.py +++ b/plugins/ui/src/deephaven/ui/components/item.py @@ -14,4 +14,5 @@ def item(*children: Stringable, **props: Any) -> ItemElement: children: The options to render within the item. **props: Any other Item prop. """ - return BaseElement("deephaven.ui.components.Item", *children, **props) + # TODO: Revert to deephaven.ui.components, need Brian's change + return BaseElement("deephaven.ui.spectrum.Item", *children, **props) diff --git a/plugins/ui/src/deephaven/ui/components/spectrum/basic.py b/plugins/ui/src/deephaven/ui/components/spectrum/basic.py index cce9ae815..3eabd1d50 100644 --- a/plugins/ui/src/deephaven/ui/components/spectrum/basic.py +++ b/plugins/ui/src/deephaven/ui/components/spectrum/basic.py @@ -61,14 +61,6 @@ def icon_wrapper(*children, **props): return spectrum_element("Icon", *children, **props) -def item(*children, **props): - """ - Python implementation for the Adobe React Spectrum Item component. - Used with Tabs: https://react-spectrum.adobe.com/react-spectrum/Tabs.html - """ - return spectrum_element("Item", *children, **props) - - def illustrated_message(*children, **props): """ Python implementation for the Adobe React Spectrum IllustratedMessage component. diff --git a/plugins/ui/src/js/src/elements/SpectrumElementUtils.ts b/plugins/ui/src/js/src/elements/SpectrumElementUtils.ts index 9cd44b1d0..d6a546fdf 100644 --- a/plugins/ui/src/js/src/elements/SpectrumElementUtils.ts +++ b/plugins/ui/src/js/src/elements/SpectrumElementUtils.ts @@ -12,7 +12,6 @@ import { Switch, Tabs, TabList, - TabPanels, Text, ToggleButton, View, @@ -25,6 +24,7 @@ import { Form, RangeSlider, Slider, + TabPanels, TextField, } from './spectrum'; import { ELEMENT_KEY, ElementNode, isElementNode } from './ElementUtils'; diff --git a/plugins/ui/src/js/src/elements/spectrum/TabPanels.tsx b/plugins/ui/src/js/src/elements/spectrum/TabPanels.tsx new file mode 100644 index 000000000..6214891da --- /dev/null +++ b/plugins/ui/src/js/src/elements/spectrum/TabPanels.tsx @@ -0,0 +1,77 @@ +import React from 'react'; +import { + FlexProps, + Item, + TabPanels as SpectrumTabPanels, + SpectrumTabPanelsProps, +} from '@adobe/react-spectrum'; +import Flex from './Flex'; + +function isFlexComponent( + item: JSX.Element +): item is React.ReactElement { + return React.isValidElement(item) && item.type === Flex; +} + +function isItemComponent(item: JSX.Element): boolean { + return React.isValidElement(item) && item.type === Item; +} + +/** + * Normalizes the children of the TabsPanel component, returning an array of children. + * If there's only one child and it's a flex component, it will set `height=100%` on it if no height is already set. + * Otherwise it does not fill the space, and that's almost certainly not what the user wants. + * @param item Item to normalize + * @returns The normalized children + */ +function mapTabPanelsItemChild(item: JSX.Element): JSX.Element { + if (isFlexComponent(item)) { + const { props } = item; + return React.cloneElement(item, { + height: '100%', + ...props, + }); + } + return item; +} + +function mapTabPanelsChild(child: JSX.Element): JSX.Element { + if (isItemComponent(child)) { + const { props } = child; + const { children } = props; + return React.cloneElement(child, { + ...props, + children: Array.isArray(children) + ? children.map(mapTabPanelsItemChild) + : mapTabPanelsItemChild(children), + }); + } + return child; +} + +/** + * Normalizes the children of the TabsPanel component, returning an array of children. + * If there's only one child and it's a flex component, it will set `height=100%` on it if no height is already set. + * Otherwise it does not fill the space, and that's almost certainly not what the user wants. + * @param children Children to normalize + * @returns The normalized children + */ +function mapTabPanelsChildren(children: React.ReactNode): JSX.Element[] { + const childrenArray = Array.isArray(children) ? children : [children]; + return childrenArray.map(mapTabPanelsChild); +} + +function TabPanels(props: SpectrumTabPanelsProps) { + const { children, ...otherProps } = props; + + return ( + // eslint-disable-next-line react/jsx-props-no-spreading + + {mapTabPanelsChildren(children)} + + ); +} + +TabPanels.displayName = 'TabPanels'; + +export default TabPanels; diff --git a/plugins/ui/src/js/src/elements/spectrum/index.ts b/plugins/ui/src/js/src/elements/spectrum/index.ts index 27c96d7f3..c7b144d93 100644 --- a/plugins/ui/src/js/src/elements/spectrum/index.ts +++ b/plugins/ui/src/js/src/elements/spectrum/index.ts @@ -10,4 +10,5 @@ export { default as Flex } from './Flex'; export { default as Form } from './Form'; export { default as RangeSlider } from './RangeSlider'; export { default as Slider } from './Slider'; +export { default as TabPanels } from './TabPanels'; export { default as TextField } from './TextField';