Skip to content

Commit

Permalink
UI Picker JS (#292)
Browse files Browse the repository at this point in the history
  • Loading branch information
bmingles committed Feb 29, 2024
1 parent 9433a98 commit d0ed337
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 46 deletions.
34 changes: 34 additions & 0 deletions plugins/ui/src/js/src/elements/ElementConstants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type * as icons from '@deephaven/icons';

/** Namespaces */
export const UI_COMPONENTS_NAMESPACE = 'deephaven.ui.components';
export const UI_ELEMENTS_NAMESPACE = 'deephaven.ui.elements';

/** Table */
export const UITABLE_ELEMENT_TYPE = `${UI_ELEMENTS_NAMESPACE}.UITable` as const;
export type UITableElementName = typeof UITABLE_ELEMENT_TYPE;

/** Layout */
export const PANEL_ELEMENT_NAME = `${UI_COMPONENTS_NAMESPACE}.Panel` as const;
export const ROW_ELEMENT_NAME = `${UI_COMPONENTS_NAMESPACE}.Row` as const;
export const COLUMN_ELEMENT_NAME = `${UI_COMPONENTS_NAMESPACE}.Column` as const;
export const STACK_ELEMENT_NAME = `${UI_COMPONENTS_NAMESPACE}.Stack` as const;
export const DASHBOARD_ELEMENT_NAME =
`${UI_COMPONENTS_NAMESPACE}.Dashboard` as const;

export type PanelElementType = typeof PANEL_ELEMENT_NAME;
export type RowElementType = typeof ROW_ELEMENT_NAME;
export type ColumnElementType = typeof COLUMN_ELEMENT_NAME;
export type StackElementType = typeof STACK_ELEMENT_NAME;
export type DashboardElementType = typeof DASHBOARD_ELEMENT_NAME;

/** Icons */
export const ICON_ELEMENT_TYPE_PREFIX = 'deephaven.ui.icons.';
export type IconElementName =
`${typeof ICON_ELEMENT_TYPE_PREFIX}${keyof typeof icons}`;

/** Specific Components */
export const ITEM_ELEMENT_NAME = `${UI_COMPONENTS_NAMESPACE}.Item` as const;
export const PICKER_ELEMENT_NAME = `${UI_COMPONENTS_NAMESPACE}.Picker` as const;
export const SECTION_ELEMENT_NAME =
`${UI_COMPONENTS_NAMESPACE}.Section` as const;
6 changes: 1 addition & 5 deletions plugins/ui/src/js/src/elements/IconElementUtils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import * as icons from '@deephaven/icons';
import { IconElementName, ICON_ELEMENT_TYPE_PREFIX } from './ElementConstants';
import { ELEMENT_KEY, ElementNode, isElementNode } from './ElementUtils';

export const ICON_ELEMENT_TYPE_PREFIX = 'deephaven.ui.icons.';

export type IconElementName =
`${typeof ICON_ELEMENT_TYPE_PREFIX}${keyof typeof icons}`;

/**
* Describes an icon element that can be rendered in the UI.
* The name of the icon is the name of the element without the prefix.
Expand Down
12 changes: 12 additions & 0 deletions plugins/ui/src/js/src/elements/Picker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import {
Picker as DHPicker,
PickerProps as DHPickerProps,
} from '@deephaven/components';

function Picker(props: DHPickerProps) {
// eslint-disable-next-line react/jsx-props-no-spreading
return <DHPicker {...props} />;
}

export default Picker;
5 changes: 1 addition & 4 deletions plugins/ui/src/js/src/elements/UITableUtils.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import type { WidgetExportedObject } from '@deephaven/jsapi-types';
import { DehydratedSort } from '@deephaven/iris-grid';
import { ELEMENT_KEY, ElementNode, isElementNode } from './ElementUtils';

export const UITABLE_ELEMENT_TYPE = 'deephaven.ui.elements.UITable';

export type UITableElementName = typeof UITABLE_ELEMENT_TYPE;
import { UITableElementName, UITABLE_ELEMENT_TYPE } from './ElementConstants';

export interface UITableProps {
table: WidgetExportedObject;
Expand Down
9 changes: 9 additions & 0 deletions plugins/ui/src/js/src/elements/spectrum/Item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* 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 default Item;
9 changes: 9 additions & 0 deletions plugins/ui/src/js/src/elements/spectrum/Section.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* 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 default Section;
2 changes: 2 additions & 0 deletions plugins/ui/src/js/src/elements/spectrum/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export { default as ActionButton } from './ActionButton';
export { default as Button } from './Button';
export { default as Flex } from './Flex';
export { default as Form } from './Form';
export { default as Item } from './Item';
export { default as RangeSlider } from './RangeSlider';
export { default as Slider } from './Slider';
export { default as Section } from './Section';
export { default as TextField } from './TextField';
24 changes: 12 additions & 12 deletions plugins/ui/src/js/src/layout/LayoutUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ import Column from './Column';
import Row from './Row';
import Stack from './Stack';
import ReactPanel from './ReactPanel';

export const PANEL_ELEMENT_NAME = 'deephaven.ui.components.Panel';
export const ROW_ELEMENT_NAME = 'deephaven.ui.components.Row';
export const COLUMN_ELEMENT_NAME = 'deephaven.ui.components.Column';
export const STACK_ELEMENT_NAME = 'deephaven.ui.components.Stack';
export const DASHBOARD_ELEMENT_NAME = 'deephaven.ui.components.Dashboard';

export type PanelElementType = typeof PANEL_ELEMENT_NAME;
export type RowElementType = typeof ROW_ELEMENT_NAME;
export type ColumnElementType = typeof COLUMN_ELEMENT_NAME;
export type StackElementType = typeof STACK_ELEMENT_NAME;
export type DashboardElementType = typeof DASHBOARD_ELEMENT_NAME;
import {
ColumnElementType,
COLUMN_ELEMENT_NAME,
DashboardElementType,
DASHBOARD_ELEMENT_NAME,
PanelElementType,
PANEL_ELEMENT_NAME,
RowElementType,
ROW_ELEMENT_NAME,
StackElementType,
STACK_ELEMENT_NAME,
} from '../elements/ElementConstants';

export type GoldenLayoutParent = RowOrColumn | GLStack | Root;

Expand Down
69 changes: 44 additions & 25 deletions plugins/ui/src/js/src/widget/WidgetUtils.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
/* eslint-disable react/jsx-props-no-spreading */
/* eslint-disable import/prefer-default-export */
import React from 'react';
import React, { ComponentType } from 'react';
import {
ElementNode,
ELEMENT_KEY,
isElementNode,
isExportedObject,
isFragmentElementNode,
} from '../elements/ElementUtils';
Expand All @@ -12,21 +14,49 @@ import { isSpectrumElementNode } from '../elements/SpectrumElementUtils';
import SpectrumElementView from '../elements/SpectrumElementView';
import { isIconElementNode } from '../elements/IconElementUtils';
import IconElementView from '../elements/IconElementView';
import { isUITable } from '../elements/UITableUtils';
import UITable from '../elements/UITable';
import {
isColumnElementNode,
isDashboardElementNode,
isPanelElementNode,
isRowElementNode,
isStackElementNode,
} from '../layout/LayoutUtils';
COLUMN_ELEMENT_NAME,
DASHBOARD_ELEMENT_NAME,
ITEM_ELEMENT_NAME,
PANEL_ELEMENT_NAME,
PICKER_ELEMENT_NAME,
ROW_ELEMENT_NAME,
SECTION_ELEMENT_NAME,
STACK_ELEMENT_NAME,
UITABLE_ELEMENT_TYPE,
} from '../elements/ElementConstants';
import ReactPanel from '../layout/ReactPanel';
import ObjectView from '../elements/ObjectView';
import Row from '../layout/Row';
import Stack from '../layout/Stack';
import Column from '../layout/Column';
import Dashboard from '../layout/Dashboard';
import Picker from '../elements/Picker';
import { Item, Section } from '../elements/spectrum';

/*
* Map element node names to their corresponding React components
*/
const elementComponentMap = {
[PANEL_ELEMENT_NAME]: ReactPanel,
[ROW_ELEMENT_NAME]: Row,
[COLUMN_ELEMENT_NAME]: Column,
[STACK_ELEMENT_NAME]: Stack,
[DASHBOARD_ELEMENT_NAME]: Dashboard,
[ITEM_ELEMENT_NAME]: Item,
[PICKER_ELEMENT_NAME]: Picker,
[SECTION_ELEMENT_NAME]: Section,
[UITABLE_ELEMENT_TYPE]: UITable,
} as const;

export function getComponentTypeForElement<P extends Record<string, unknown>>(
element: ElementNode<string, P>
): ComponentType<P> | null {
return (elementComponentMap[
element[ELEMENT_KEY] as keyof typeof elementComponentMap
] ?? null) as ComponentType<P> | null;
}

export function getComponentForElement(element: ElementNode): React.ReactNode {
// Need to convert the children of the element if they are exported objects to an ObjectView
Expand Down Expand Up @@ -59,27 +89,16 @@ export function getComponentForElement(element: ElementNode): React.ReactNode {
if (isIconElementNode(newElement)) {
return IconElementView({ element: newElement });
}
if (isUITable(newElement)) {
return <UITable {...newElement.props} />;
}
if (isPanelElementNode(newElement)) {
return <ReactPanel {...newElement.props} />;
}
if (isFragmentElementNode(newElement)) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return <>{newElement.props?.children}</>;
}
if (isRowElementNode(newElement)) {
return <Row {...newElement.props} />;
}
if (isColumnElementNode(newElement)) {
return <Column {...newElement.props} />;
}
if (isStackElementNode(newElement)) {
return <Stack {...newElement.props} />;
}
if (isDashboardElementNode(newElement)) {
return <Dashboard {...newElement.props} />;
if (isElementNode(newElement)) {
const Component = getComponentTypeForElement(newElement);

if (Component != null) {
return <Component {...newElement.props} />;
}
}

return newElement.props?.children;
Expand Down

0 comments on commit d0ed337

Please sign in to comment.