From 6e281dd2304dc06636a004c0de3567fcdd360e88 Mon Sep 17 00:00:00 2001 From: Mike Bender Date: Wed, 11 Mar 2026 18:08:00 -0400 Subject: [PATCH 01/15] feat: DH-21757: WidgetPlugin support in deephaven.ui - Needs https://github.com/deephaven/web-client-ui/pull/2648 - WidgetPlugin just registers directly - Allows for nested ui.resolve deephaven.ui components - Still maintain DashboardPlugin to handle legacy behaviour - Works with the ui_home_screen, nested dashboards, etc - Styling a little bit different (ui.panel is automatically wrapped in a nested dashboard rather than opening up panels in the existing dashboard like before) - Dashboard now has a `show_headers` option that can be set to False to not show headers on a dashboard. Useful if you're doing a homescreen type dashboard --- .../src/deephaven/ui/components/dashboard.py | 9 +- .../deephaven/ui/elements/DashboardElement.py | 13 +- plugins/ui/src/js/src/DashboardPlugin.tsx | 87 ++----- plugins/ui/src/js/src/UIComponent.tsx | 54 +++++ plugins/ui/src/js/src/UIWidget.tsx | 22 ++ plugins/ui/src/js/src/UIWidgetPlugin.ts | 22 ++ plugins/ui/src/js/src/index.ts | 24 +- plugins/ui/src/js/src/layout/Dashboard.tsx | 13 +- .../ui/src/js/src/layout/NestedDashboard.tsx | 44 +++- plugins/ui/src/js/src/layout/ReactPanel.tsx | 11 +- .../ui/src/js/src/layout/ReactPanelManager.ts | 5 +- .../src/js/src/layout/WidgetStatusContext.tsx | 7 +- .../ui/src/js/src/layout/usePanelManager.ts | 22 +- plugins/ui/src/js/src/styles.scss | 12 + .../js/src/widget/DashboardWidgetHandler.tsx | 26 +++ .../ui/src/js/src/widget/DocumentHandler.tsx | 11 +- .../ui/src/js/src/widget/DocumentUtils.tsx | 15 +- .../ui/src/js/src/widget/WidgetHandler.tsx | 40 +--- tests/app.d/tests.app | 3 +- tests/app.d/ui_home_screen.py | 217 ++++++++++++++++++ tests/ui_home_screen.spec.ts | 21 ++ 21 files changed, 533 insertions(+), 145 deletions(-) create mode 100644 plugins/ui/src/js/src/UIComponent.tsx create mode 100644 plugins/ui/src/js/src/UIWidget.tsx create mode 100644 plugins/ui/src/js/src/UIWidgetPlugin.ts create mode 100644 tests/app.d/ui_home_screen.py create mode 100644 tests/ui_home_screen.spec.ts diff --git a/plugins/ui/src/deephaven/ui/components/dashboard.py b/plugins/ui/src/deephaven/ui/components/dashboard.py index 44ae34491..f91ffce1f 100644 --- a/plugins/ui/src/deephaven/ui/components/dashboard.py +++ b/plugins/ui/src/deephaven/ui/components/dashboard.py @@ -4,15 +4,20 @@ from ..elements import DashboardElement, FunctionElement -def dashboard(element: FunctionElement) -> DashboardElement: +def dashboard( + element: FunctionElement, + *, + show_headers: bool = True, +) -> DashboardElement: """ A dashboard is the container for an entire layout. Args: element: Element to render as the dashboard. The element should render a layout that contains 1 root column or row. + show_headers: Whether to show headers on the dashboard panels. Defaults to True. Returns: The rendered dashboard. """ - return DashboardElement(element) + return DashboardElement(element, show_headers=show_headers) diff --git a/plugins/ui/src/deephaven/ui/elements/DashboardElement.py b/plugins/ui/src/deephaven/ui/elements/DashboardElement.py index af8310eb1..d1a3b1e60 100644 --- a/plugins/ui/src/deephaven/ui/elements/DashboardElement.py +++ b/plugins/ui/src/deephaven/ui/elements/DashboardElement.py @@ -8,5 +8,14 @@ class DashboardElement(BaseElement): - def __init__(self, element: FunctionElement): - super().__init__("deephaven.ui.components.Dashboard", element) + def __init__( + self, + element: FunctionElement, + *, + show_headers: bool = True, + ): + super().__init__( + "deephaven.ui.components.Dashboard", + element, + show_headers=show_headers, + ) diff --git a/plugins/ui/src/js/src/DashboardPlugin.tsx b/plugins/ui/src/js/src/DashboardPlugin.tsx index 9e78dcc8a..50e0e5dfe 100644 --- a/plugins/ui/src/js/src/DashboardPlugin.tsx +++ b/plugins/ui/src/js/src/DashboardPlugin.tsx @@ -1,5 +1,4 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { nanoid } from 'nanoid'; import { DashboardPluginComponentProps, LayoutManagerContext, @@ -7,18 +6,14 @@ import { PanelEvent, useListener, useDashboardPluginData, - emitCreateDashboard, WidgetDescriptor, - PanelOpenEventDetail, DEFAULT_DASHBOARD_ID, useDashboardPanel, } from '@deephaven/dashboard'; import Log from '@deephaven/log'; import { DeferredApiBootstrap } from '@deephaven/jsapi-bootstrap'; -import { dh } from '@deephaven/jsapi-types'; import { ErrorBoundary } from '@deephaven/components'; import { useDebouncedCallback } from '@deephaven/react-hooks'; -import styles from './styles.scss?inline'; import { ReadonlyWidgetData, WidgetDataUpdate, @@ -27,11 +22,6 @@ import { import PortalPanel from './layout/PortalPanel'; import PortalPanelManager from './layout/PortalPanelManager'; import DashboardWidgetHandler from './widget/DashboardWidgetHandler'; -import { - getPreservedData, - DASHBOARD_ELEMENT, - WIDGET_ELEMENT, -} from './widget/WidgetUtils'; import { usePanelId } from './layout/ReactPanelContext'; const PLUGIN_NAME = '@deephaven/js-plugin-ui.DashboardPlugin'; @@ -63,6 +53,13 @@ interface WidgetWrapper { data?: ReadonlyWidgetData; } +/** + * Handle legacy behaviour of an open widget being saved with the dashboard. + * + * Now UIWidgetPlugin is responsible for opening widgets in the dashboard. + * @param props Dashboard plugin props + * @returns Dashboard plugin content, which is responsible for handling legacy behaviour of an open widget being saved with the dashboard + */ function InnerDashboardPlugin( props: DashboardPluginComponentProps ): JSX.Element | null { @@ -78,66 +75,6 @@ function InnerDashboardPlugin( ReadonlyMap >(new Map()); - const handleWidgetOpen = useCallback( - ({ widgetId, widget }: { widgetId: string; widget: WidgetDescriptor }) => { - log.debug('Opening widget with ID', widgetId, widget); - setWidgetMap(prevWidgetMap => { - const newWidgetMap = new Map(prevWidgetMap); - const oldWidget = newWidgetMap.get(widgetId); - newWidgetMap.set(widgetId, { - id: widgetId, - widget, - data: getPreservedData(oldWidget?.data), - }); - return newWidgetMap; - }); - }, - [] - ); - - const handleDashboardOpen = useCallback( - ({ - widget, - dashboardId, - }: { - widget: WidgetDescriptor; - dashboardId: string; - }) => { - const { name: title } = widget; - log.debug('Emitting create dashboard event for', dashboardId, widget); - emitCreateDashboard(layout.eventHub, { - pluginId: PLUGIN_NAME, - title: title ?? 'Untitled', - data: { openWidgets: { [dashboardId]: { descriptor: widget } } }, - }); - }, - [layout.eventHub] - ); - - const handlePanelOpen = useCallback( - ({ - panelId: widgetId = nanoid(), - widget, - }: PanelOpenEventDetail) => { - const { type } = widget; - - switch (type) { - case WIDGET_ELEMENT: { - handleWidgetOpen({ widgetId, widget }); - break; - } - case DASHBOARD_ELEMENT: { - handleDashboardOpen({ widget, dashboardId: widgetId }); - break; - } - default: { - break; - } - } - }, - [handleDashboardOpen, handleWidgetOpen] - ); - useEffect( function loadInitialPluginData() { if (initialPluginData == null) { @@ -203,8 +140,6 @@ function InnerDashboardPlugin( }); }, []); - // TODO: We need to change up the event system for how objects are opened, since in this case it could be opening multiple panels - useListener(layout.eventHub, PanelEvent.OPEN, handlePanelOpen); useListener(layout.eventHub, PanelEvent.CLOSE, handlePanelClose); const sendPluginDataUpdate = useCallback( @@ -282,12 +217,18 @@ function InnerDashboardPlugin( return ( - {widgetHandlers} ); } +/** + * Dashboard plugin that registers the PortalPanel type for deephaven.ui + * + * It's also responsible for handling legacy behaviour, for old dashboards that may have opened a deephaven.ui widget previously. + * @param props Dashboard plugin props + * @returns Dashboard plugin + */ export function DashboardPlugin( props: DashboardPluginComponentProps ): JSX.Element | null { diff --git a/plugins/ui/src/js/src/UIComponent.tsx b/plugins/ui/src/js/src/UIComponent.tsx new file mode 100644 index 000000000..d2597ae45 --- /dev/null +++ b/plugins/ui/src/js/src/UIComponent.tsx @@ -0,0 +1,54 @@ +import React, { useCallback, useMemo } from 'react'; +import { UriVariableDescriptor } from '@deephaven/jsapi-bootstrap'; +import type { dh } from '@deephaven/jsapi-types'; +import { + usePersistentState, + type WidgetComponentProps, +} from '@deephaven/plugin'; +import { WidgetDescriptor } from '@deephaven/dashboard'; +import { nanoid } from 'nanoid'; +import { WidgetData, WidgetDataUpdate } from './widget/WidgetTypes'; +import WidgetHandler from './widget/WidgetHandler'; + +type UIComponentProps = WidgetComponentProps & { + // TODO: We shouldn't need this, should be added to the WidgetComponentProps type + metadata?: WidgetDescriptor; + + // Might be loading a URI resolved widget... + uri?: UriVariableDescriptor; +}; + +export function UIComponent(props: UIComponentProps): JSX.Element | null { + const { metadata: widgetDescriptor, uri, __dhId } = props; + + const [widgetData, setWidgetData] = usePersistentState< + WidgetData | undefined + >(undefined, { type: 'UIComponentWidgetData', version: 1 }); + + const id = useMemo( + () => __dhId ?? widgetDescriptor?.id ?? nanoid(), + [__dhId, widgetDescriptor] + ); + + const handleDataChange = useCallback( + (data: WidgetDataUpdate) => { + setWidgetData(oldData => ({ ...oldData, ...data })); + }, + [setWidgetData] + ); + + const descriptor = uri ?? widgetDescriptor; + if (descriptor == null) { + throw new Error('No widget descriptor'); + } + return ( + + ); +} + +export default UIComponent; diff --git a/plugins/ui/src/js/src/UIWidget.tsx b/plugins/ui/src/js/src/UIWidget.tsx new file mode 100644 index 000000000..a3feff652 --- /dev/null +++ b/plugins/ui/src/js/src/UIWidget.tsx @@ -0,0 +1,22 @@ +import type { dh } from '@deephaven/jsapi-types'; +import { type WidgetComponentProps } from '@deephaven/plugin'; +import { WidgetDescriptor } from '@deephaven/dashboard'; +import UIComponent from './UIComponent'; +import PortalPanel from './layout/PortalPanel'; + +type UIWidgetProps = WidgetComponentProps & { + // TODO: We shouldn't need this, should be added to the WidgetComponentProps type + metadata?: WidgetDescriptor; +}; + +export function UIWidget(props: UIWidgetProps): JSX.Element | null { + const { metadata: widgetDescriptor } = props; + if (widgetDescriptor?.type === PortalPanel.displayName) { + return null; + } + + // eslint-disable-next-line react/jsx-props-no-spreading + return ; +} + +export default UIWidget; diff --git a/plugins/ui/src/js/src/UIWidgetPlugin.ts b/plugins/ui/src/js/src/UIWidgetPlugin.ts new file mode 100644 index 000000000..7772af0a4 --- /dev/null +++ b/plugins/ui/src/js/src/UIWidgetPlugin.ts @@ -0,0 +1,22 @@ +import { type WidgetPlugin, PluginType } from '@deephaven/plugin'; +import { vsGraph } from '@deephaven/icons'; +import type { dh } from '@deephaven/jsapi-types'; +import { DASHBOARD_ELEMENT, WIDGET_ELEMENT } from './widget/WidgetUtils'; +import PortalPanel from './layout/PortalPanel'; +import UIWidget from './UIWidget'; +import styles from './styles.scss?inline'; + +// We need to inject the styles into the document when we're loaded... we only want to do this once. +const styleElement = document.createElement('style'); +styleElement.textContent = styles; +document.head.appendChild(styleElement); + +export const UIWidgetPlugin: WidgetPlugin = { + name: '@deephaven/js-plugin-ui', + type: PluginType.WIDGET_PLUGIN, + supportedTypes: [WIDGET_ELEMENT, DASHBOARD_ELEMENT, PortalPanel.displayName], + component: UIWidget, + icon: vsGraph, +}; + +export default UIWidgetPlugin; diff --git a/plugins/ui/src/js/src/index.ts b/plugins/ui/src/js/src/index.ts index bd84ac498..fdcf0d741 100644 --- a/plugins/ui/src/js/src/index.ts +++ b/plugins/ui/src/js/src/index.ts @@ -1 +1,23 @@ -export * from './DashboardPlugin'; +import { PluginType } from '@deephaven/plugin'; +import { UIWidgetPlugin } from './UIWidgetPlugin'; +import { DashboardPlugin } from './DashboardPlugin'; + +// TODO: Remove local MultiPlugin type once @deephaven/plugin is updated +// to include it (see deephaven/web-client-ui composite-plugins branch) +const MULTI_PLUGIN = 'MultiPlugin' as const; + +const UIDashboardPlugin = { + name: '@deephaven/js-plugin-ui.DashboardPlugin', + type: PluginType.DASHBOARD_PLUGIN as string, + component: DashboardPlugin, +}; + +const UIMultiPlugin = { + name: '@deephaven/js-plugin-ui', + type: MULTI_PLUGIN as string, + plugins: [UIWidgetPlugin, UIDashboardPlugin], +}; + +export { DashboardPlugin }; + +export default UIMultiPlugin; diff --git a/plugins/ui/src/js/src/layout/Dashboard.tsx b/plugins/ui/src/js/src/layout/Dashboard.tsx index 91ce24610..fea6aacfa 100644 --- a/plugins/ui/src/js/src/layout/Dashboard.tsx +++ b/plugins/ui/src/js/src/layout/Dashboard.tsx @@ -1,6 +1,7 @@ import React from 'react'; +import { usePanelId as useLayoutPanelId } from '@deephaven/dashboard'; import { ElementIdProps, type DashboardElementProps } from './LayoutUtils'; -import { usePanelId } from './ReactPanelContext'; +import { usePanelId as useReactPanelId } from './ReactPanelContext'; import NestedDashboard from './NestedDashboard'; import DashboardContent from './DashboardContent'; @@ -12,12 +13,14 @@ import DashboardContent from './DashboardContent'; */ function Dashboard({ children, - __dhId, + ...otherProps }: DashboardElementProps & ElementIdProps): JSX.Element | null { - const contextPanelId = usePanelId(); - const isNested = contextPanelId != null; + const contextPanelId = useLayoutPanelId(); + const reactPanelId = useReactPanelId(); + const isNested = contextPanelId != null || reactPanelId != null; if (isNested) { - return {children}; + // eslint-disable-next-line react/jsx-props-no-spreading + return {children}; } return {children}; diff --git a/plugins/ui/src/js/src/layout/NestedDashboard.tsx b/plugins/ui/src/js/src/layout/NestedDashboard.tsx index b7ca12ef5..2feac30ac 100644 --- a/plugins/ui/src/js/src/layout/NestedDashboard.tsx +++ b/plugins/ui/src/js/src/layout/NestedDashboard.tsx @@ -1,10 +1,37 @@ -import React, { PropsWithChildren, useState } from 'react'; -import { Dashboard as DHCDashboard } from '@deephaven/dashboard'; +import React, { PropsWithChildren, useMemo, useState } from 'react'; +import { + Dashboard as DHCDashboard, + useDashboardPanel, + DashboardPluginComponentProps, + assertIsDashboardPluginProps, +} from '@deephaven/dashboard'; import { useDashboardPlugins } from '@deephaven/plugin'; import NestedDashboardContent from './NestedDashboardContent'; import { ElementIdProps } from './LayoutUtils'; +import PortalPanel from './PortalPanel'; -type NestedDashboardProps = PropsWithChildren; +type NestedDashboardProps = PropsWithChildren & { + /** + * Whether to show the headers on panels in this dashboard. Defaults to `true` + */ + showHeaders?: boolean; +}; + +function NestedDashboardPlugin( + props: Partial +): JSX.Element | null { + assertIsDashboardPluginProps(props); + useDashboardPanel({ + dashboardProps: props, + componentName: PortalPanel.displayName, + component: PortalPanel, + + // We don't want these panels to be triggered by a widget opening, we want to control how it is opened later + supportedTypes: [], + }); + + return null; +} /** * A dashboard that can be nested inside a panel. @@ -12,16 +39,25 @@ type NestedDashboardProps = PropsWithChildren; */ function NestedDashboard({ children, + showHeaders = true, __dhId, }: NestedDashboardProps): JSX.Element { const plugins = useDashboardPlugins(); const [layoutInitialized, setLayoutInitialized] = useState(false); + const layoutSettings = useMemo( + () => ({ hasHeaders: showHeaders }), + [showHeaders] + ); return (
{/* DHCDashboard creates GoldenLayout and provides LayoutManagerContext */} - setLayoutInitialized(true)}> + setLayoutInitialized(true)} + layoutSettings={layoutSettings} + > {plugins} + {layoutInitialized && ( {children} diff --git a/plugins/ui/src/js/src/layout/ReactPanel.tsx b/plugins/ui/src/js/src/layout/ReactPanel.tsx index 51fa0d7c1..70da085da 100644 --- a/plugins/ui/src/js/src/layout/ReactPanel.tsx +++ b/plugins/ui/src/js/src/layout/ReactPanel.tsx @@ -13,6 +13,7 @@ import { PanelIdContext, useLayoutManager, useListener, + usePanelId as useLayoutPanelId, } from '@deephaven/dashboard'; import { View, @@ -101,7 +102,8 @@ function ReactPanel({ useReactPanel(); const portalManager = usePortalPanelManager(); const portal = portalManager.get(panelId); - const panelTitle = title ?? metadata?.name ?? ''; + const panelTitle = + title ?? (typeof metadata === 'string' ? metadata : metadata?.name ?? ''); const [initialData, setInitialData] = useState(getInitialData()); const onErrorReset = useCallback(() => { // Not EMPTY_ARRAY, because we always want to trigger a re-render @@ -124,6 +126,10 @@ function ReactPanel({ const contentKey = useMemo(() => nanoid(), [metadata]); const parent = useParentItem(); + const layoutPanelId = useLayoutPanelId(); + // If we're opening these panels at the top level, they should be closable. + // We may make this settable as a prop on the panel in the future + const isClosable = layoutPanelId == null; const contextPanelId = usePanelId(); if (contextPanelId != null) { throw new NestedPanelError( @@ -177,6 +183,7 @@ function ReactPanel({ props: { metadata }, title: panelTitle, id: panelId, + isClosable, }; LayoutUtils.openComponent({ root: parent, config }); @@ -203,7 +210,7 @@ function ReactPanel({ LayoutUtils.renameComponent(parent, itemConfig, panelTitle); } }, - [parent, metadata, onOpen, panelId, panelTitle] + [isClosable, parent, metadata, onOpen, panelId, panelTitle] ); const widgetStatus = useWidgetStatus(); diff --git a/plugins/ui/src/js/src/layout/ReactPanelManager.ts b/plugins/ui/src/js/src/layout/ReactPanelManager.ts index c92421ce0..00a42cc97 100644 --- a/plugins/ui/src/js/src/layout/ReactPanelManager.ts +++ b/plugins/ui/src/js/src/layout/ReactPanelManager.ts @@ -1,4 +1,5 @@ import { PanelProps } from '@deephaven/dashboard'; +import { UriVariableDescriptor } from '@deephaven/jsapi-bootstrap'; import { useContextOrThrow } from '@deephaven/react-hooks'; import { createContext, useCallback, useMemo } from 'react'; @@ -11,7 +12,7 @@ export interface ReactPanelManager { * Updating the metadata will cause the panel to be re-opened, or replaced if it is closed. * Can also be used for rehydration. */ - metadata: PanelProps['metadata']; + metadata: PanelProps['metadata'] | UriVariableDescriptor; /** Triggered when a panel is opened */ onOpen: (panelId: string) => void; @@ -46,7 +47,7 @@ export interface ReactPanelControl { * Updating the metadata will cause the panel to be re-opened, or replaced if it is closed. * Can also be used for rehydration. */ - metadata: PanelProps['metadata']; + metadata: PanelProps['metadata'] | UriVariableDescriptor; /** Must be called when the panel is opened */ onOpen: () => void; diff --git a/plugins/ui/src/js/src/layout/WidgetStatusContext.tsx b/plugins/ui/src/js/src/layout/WidgetStatusContext.tsx index c2c7874c6..daa72e8a4 100644 --- a/plugins/ui/src/js/src/layout/WidgetStatusContext.tsx +++ b/plugins/ui/src/js/src/layout/WidgetStatusContext.tsx @@ -1,20 +1,21 @@ import { WidgetDescriptor } from '@deephaven/dashboard'; +import { UriVariableDescriptor } from '@deephaven/jsapi-bootstrap'; import { createContext } from 'react'; export type WidgetStatusLoading = { status: 'loading'; - descriptor: WidgetDescriptor; + descriptor: WidgetDescriptor | UriVariableDescriptor; }; export type WidgetStatusError = { status: 'error'; - descriptor: WidgetDescriptor; + descriptor: WidgetDescriptor | UriVariableDescriptor; error: NonNullable; }; export type WidgetStatusReady = { status: 'ready'; - descriptor: WidgetDescriptor; + descriptor: WidgetDescriptor | UriVariableDescriptor; }; export type WidgetStatus = diff --git a/plugins/ui/src/js/src/layout/usePanelManager.ts b/plugins/ui/src/js/src/layout/usePanelManager.ts index 65bc2169b..41f57f005 100644 --- a/plugins/ui/src/js/src/layout/usePanelManager.ts +++ b/plugins/ui/src/js/src/layout/usePanelManager.ts @@ -1,6 +1,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { nanoid } from 'nanoid'; import { WidgetDescriptor } from '@deephaven/dashboard'; +import { UriVariableDescriptor } from '@deephaven/jsapi-bootstrap'; import Log from '@deephaven/log'; import { EMPTY_ARRAY, EMPTY_FUNCTION } from '@deephaven/utils'; import { ReactPanelManager } from './ReactPanelManager'; @@ -16,7 +17,7 @@ const EMPTY_OBJECT = Object.freeze({}); export interface UsePanelManagerProps { /** Definition of the widget used to create this document. Used for titling panels if necessary. */ - widget: WidgetDescriptor; + widget: WidgetDescriptor | UriVariableDescriptor; /** * Data state to use when loading the widget. @@ -60,6 +61,14 @@ export function usePanelManager({ // We may need to check if we need to close this widget if all panels are closed const [isPanelsDirty, setPanelsDirty] = useState(false); + const id = useMemo( + () => + typeof widget === 'string' + ? widget + : widget.id ?? widget.name ?? widget.type, + [widget] + ); + const handleOpen = useCallback( (panelId: string) => { if (panelIds.current.includes(panelId)) { @@ -115,20 +124,15 @@ export function usePanelManager({ // Check if all the panels in this widget are closed // We do it outside of the `handleClose` function in case a new panel opens up in the same render cycle - log.debug2( - 'Widget', - widget.id, - 'open panel count', - panelIds.current.length - ); + log.debug2('Widget', id, 'open panel count', panelIds.current.length); if (panelIds.current.length === 0) { - log.debug('Widget', widget.id, 'closed all panels, triggering onClose'); + log.debug('Widget', id, 'closed all panels, triggering onClose'); onClose?.(); } else { onDataChange({ ...widgetData, panelIds: [...panelIds.current] }); } }, - [isPanelsDirty, widget.id, onClose, onDataChange, widgetData] + [isPanelsDirty, id, onClose, onDataChange, widgetData] ); const getPanelId = useCallback(() => { diff --git a/plugins/ui/src/js/src/styles.scss b/plugins/ui/src/js/src/styles.scss index 32871796a..98dc2b53f 100644 --- a/plugins/ui/src/js/src/styles.scss +++ b/plugins/ui/src/js/src/styles.scss @@ -91,6 +91,18 @@ } } +.dh-panel { + .dh-nested-dashboard { + .dashboard-container { + border: 1px solid var(--dh-color-bg); + } + } + &.widget-loader-deephaven\.ui\.Element, + &.widget-loader-deephaven\.ui\.Dashboard { + padding: var(--spectrum-global-dimension-size-100); + } +} + .ui-text-wrap-balance { text-wrap: balance; } diff --git a/plugins/ui/src/js/src/widget/DashboardWidgetHandler.tsx b/plugins/ui/src/js/src/widget/DashboardWidgetHandler.tsx index e4620e603..9d1c0cd4f 100644 --- a/plugins/ui/src/js/src/widget/DashboardWidgetHandler.tsx +++ b/plugins/ui/src/js/src/widget/DashboardWidgetHandler.tsx @@ -5,6 +5,8 @@ import React, { useCallback } from 'react'; import Log from '@deephaven/log'; import { WidgetDataUpdate, WidgetId } from './WidgetTypes'; import WidgetHandler, { WidgetHandlerProps } from './WidgetHandler'; +import { WIDGET_ELEMENT } from './WidgetUtils'; +import ReactPanel from '../layout/ReactPanel'; const log = Log.module('@deephaven/js-plugin-ui/DashboardWidgetHandler'); @@ -39,11 +41,35 @@ function DashboardWidgetHandler({ [onDataChange, id] ); + const { initialData, widgetDescriptor } = otherProps; + + const renderEmptyDocument = useCallback(() => { + // Document hasn't been initialized yet. Display a loading spinner if applicable. + if (widgetDescriptor.type === WIDGET_ELEMENT) { + // Rehydration. Mount ReactPanels for each panelId in the initial data + // so loading spinners or widget errors are shown + if (initialData?.panelIds != null && initialData.panelIds.length > 0) { + // Do not add a key here + // When the real document mounts, it doesn't use keys and will cause a remount + // which triggers the DocumentHandler to think the panels were closed and messes up the layout + // eslint-disable-next-line react/jsx-key + return initialData.panelIds.map(() => ); + } + // Default to a single panel so we can immediately show a loading spinner + return ; + } + + return null; + // We only want to update this callback when the widgetDescriptor changes, not every time the initialData changes. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [widgetDescriptor]); + return ( diff --git a/plugins/ui/src/js/src/widget/DocumentHandler.tsx b/plugins/ui/src/js/src/widget/DocumentHandler.tsx index 42d3020cd..edcf7cb91 100644 --- a/plugins/ui/src/js/src/widget/DocumentHandler.tsx +++ b/plugins/ui/src/js/src/widget/DocumentHandler.tsx @@ -1,5 +1,6 @@ import React from 'react'; -import { WidgetDescriptor } from '@deephaven/dashboard'; +import { usePanelId, WidgetDescriptor } from '@deephaven/dashboard'; +import { UriVariableDescriptor } from '@deephaven/jsapi-bootstrap'; import Log from '@deephaven/log'; import { ReactPanelManagerContext } from '../layout/ReactPanelManager'; import { usePanelManager } from '../layout/usePanelManager'; @@ -10,7 +11,7 @@ const log = Log.module('@deephaven/js-plugin-ui/DocumentHandler'); export type DocumentHandlerProps = React.PropsWithChildren<{ /** Definition of the widget used to create this document. Used for titling panels if necessary. */ - widget: WidgetDescriptor; + widget: WidgetDescriptor | UriVariableDescriptor; /** * Data state to use when loading the widget. @@ -40,6 +41,10 @@ function DocumentHandler({ }: DocumentHandlerProps): JSX.Element { log.debug('Rendering document', widget); + // We can tell if we're opened by the DashboardPlugin or the WidgetPlugin or nested by checking the context ID + const contextPanelId = usePanelId(); + const isNested = contextPanelId != null; + const panelManager = usePanelManager({ widget, initialData, @@ -49,7 +54,7 @@ function DocumentHandler({ return ( - {getRootChildren(children, widget)} + {getRootChildren(children, widget, isNested)} ); } diff --git a/plugins/ui/src/js/src/widget/DocumentUtils.tsx b/plugins/ui/src/js/src/widget/DocumentUtils.tsx index c145b5874..35ca7d239 100644 --- a/plugins/ui/src/js/src/widget/DocumentUtils.tsx +++ b/plugins/ui/src/js/src/widget/DocumentUtils.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { WidgetDescriptor } from '@deephaven/dashboard'; +import { UriVariableDescriptor } from '@deephaven/jsapi-bootstrap'; import ReactPanel from '../layout/ReactPanel'; import { MixedPanelsError, NoChildrenError } from '../errors'; import Dashboard from '../layout/Dashboard'; @@ -12,11 +13,13 @@ import Dashboard from '../layout/Dashboard'; * * @param children Root children of the document. * @param widget Descriptor of the widget used to create this document. Used for titling panels if necessary. + * @param isNested Whether this document is nested inside a panel. * @returns The children, wrapped in a panel if necessary. */ export function getRootChildren( children: React.ReactNode, - widget: WidgetDescriptor + widget: WidgetDescriptor | UriVariableDescriptor, + isNested = false ): React.ReactNode { if (children == null) { return null; @@ -45,13 +48,9 @@ export function getRootChildren( throw new MixedPanelsError('Cannot mix Panel and Dashboard elements'); } - if (nonLayoutCount === childrenArray.length) { - // Just wrap it in a panel - return ( - - {children} - - ); + if (panelCount > 0 && isNested) { + // Wrap it in a dashboard so it can be rendered properly + return {children}; } // It's already got layout defined, just return it diff --git a/plugins/ui/src/js/src/widget/WidgetHandler.tsx b/plugins/ui/src/js/src/widget/WidgetHandler.tsx index 6bee76bed..c1191ed97 100644 --- a/plugins/ui/src/js/src/widget/WidgetHandler.tsx +++ b/plugins/ui/src/js/src/widget/WidgetHandler.tsx @@ -17,7 +17,7 @@ import { JSONRPCServerAndClient, } from 'json-rpc-2.0'; import { useLayoutManager, WidgetDescriptor } from '@deephaven/dashboard'; -import { useWidget } from '@deephaven/jsapi-bootstrap'; +import { UriVariableDescriptor, useWidget } from '@deephaven/jsapi-bootstrap'; import type { dh } from '@deephaven/jsapi-types'; import Log from '@deephaven/log'; import { usePluginsElementMap } from '@deephaven/plugin'; @@ -44,7 +44,6 @@ import DocumentHandler from './DocumentHandler'; import { transformNode, getComponentForElement, - WIDGET_ELEMENT, wrapCallable, DASHBOARD_ELEMENT, } from './WidgetUtils'; @@ -52,7 +51,6 @@ import WidgetStatusContext, { WidgetStatus, } from '../layout/WidgetStatusContext'; import WidgetErrorView from './WidgetErrorView'; -import ReactPanel from '../layout/ReactPanel'; import Toast, { TOAST_EVENT } from '../events/Toast'; import UriExportedObject from './UriExportedObject'; import applyJsonPatch from './WidgetJsonPatch'; @@ -61,7 +59,7 @@ const log = Log.module('@deephaven/js-plugin-ui/WidgetHandler'); export interface WidgetHandlerProps { /** Widget for this to handle */ - widgetDescriptor: WidgetDescriptor; + widgetDescriptor: WidgetDescriptor | UriVariableDescriptor; /** Widget ID maintained by the DashboardPlugin */ id: string; @@ -74,6 +72,9 @@ export interface WidgetHandlerProps { /** Triggered when the data in the widget changes. Only the changed data is provided. */ onDataChange?: (data: WidgetDataUpdate) => void; + + /** What to render when the document is empty and in a loading state */ + renderEmptyDocument?: () => JSX.Element | JSX.Element[] | null; } function WidgetHandler({ @@ -82,11 +83,10 @@ function WidgetHandler({ widgetDescriptor, initialData: initialDataProp, id, + renderEmptyDocument: renderEmptyDocumentProp, }: WidgetHandlerProps): JSX.Element | null { - const layoutManager = useLayoutManager(); const { widget, error: widgetError } = useWidget(widgetDescriptor); const [isLoading, setIsLoading] = useState(true); - const [prevWidget, setPrevWidget] = useState(widget); const [prevWidgetDescriptor, setPrevWidgetDescriptor] = useState(widgetDescriptor); // Cannot use usePrevious to change setIsLoading @@ -97,16 +97,6 @@ function WidgetHandler({ setIsLoading(true); } - if (widget !== prevWidget) { - setPrevWidget(widget); - if (widget != null && widget.type === DASHBOARD_ELEMENT) { - log.info( - 'Dashboard widget has changed, removing previous elements from layout' - ); - layoutManager.root.contentItems.forEach(item => item.remove()); - } - } - if (widgetError != null && isLoading) { setIsLoading(false); } @@ -187,19 +177,9 @@ function WidgetHandler({ * Renders an empty document. This is used when the widget is loading or has an error. */ () => { - // Document hasn't been initialized yet. Display a loading spinner if applicable. - if (widgetDescriptor.type === WIDGET_ELEMENT) { - // Rehydration. Mount ReactPanels for each panelId in the initial data - // so loading spinners or widget errors are shown - if (initialData?.panelIds != null && initialData.panelIds.length > 0) { - // Do not add a key here - // When the real document mounts, it doesn't use keys and will cause a remount - // which triggers the DocumentHandler to think the panels were closed and messes up the layout - // eslint-disable-next-line react/jsx-key - return initialData.panelIds.map(() => ); - } - // Default to a single panel so we can immediately show a loading spinner - return ; + const result = renderEmptyDocumentProp?.(); + if (result != null) { + return result; } if (error != null) { // If there's an error and the document hasn't rendered yet (mostly applies to dashboards), explicitly show an error view @@ -209,7 +189,7 @@ function WidgetHandler({ // Dashboards should not have a default document. It breaks its render flow return null; }, - [error, initialData, widgetDescriptor] + [error, renderEmptyDocumentProp] ); const [uriObjectMap] = useState>(new Map()); diff --git a/tests/app.d/tests.app b/tests/app.d/tests.app index 9637ebd2a..1ab96bd76 100644 --- a/tests/app.d/tests.app +++ b/tests/app.d/tests.app @@ -16,4 +16,5 @@ file_9=ui_grid.py file_10=ui_plotly.py file_11=ag_grid.py file_12=theme_demo.py -file_13=ui_nested_dashboard.py \ No newline at end of file +file_13=ui_nested_dashboard.py +file_14=ui_home_screen.py \ No newline at end of file diff --git a/tests/app.d/ui_home_screen.py b/tests/app.d/ui_home_screen.py new file mode 100644 index 000000000..22e053176 --- /dev/null +++ b/tests/app.d/ui_home_screen.py @@ -0,0 +1,217 @@ +# ruff: noqa +# This example creates a bunch of dashboards, then creates a "home page" that displays a menu of the dashboards on the left, and the embedded dashboard on the right. +# Simply run this code snippet, then navigate to http://localhost:10000/iframe/widget/?name=home +# Creating example dashboards +from deephaven.time import dh_now +from deephaven import time_table, ui +import deephaven.plot.express as dx + + +# The control panel contain UI elements to set filtering +@ui.component +def control_panel(filter_type, set_filter_type, dates, set_dates, value, set_value): + return ui.panel( + ui.radio_group( + ui.radio("Date"), + ui.radio("Value"), + value=filter_type, + on_change=set_filter_type, + label="Filter type", + ), + ui.date_range_picker(label="Date filter", value=dates, on_change=set_dates), + ui.picker( + "A", "B", selected_key=value, on_change=set_value, label="Value filter" + ), + title="Controls", + ) + + +# The create dashboard component contains the state variables and returns the ui.row +@ui.component +def create_dashboard(start_date, end_date, table): + # State to choose the filter type + filter_type, set_filter_type = ui.use_state("Date") + + # State variable to filter by Value column + value, set_value = ui.use_state("A") + + # State variable to filter by Date column + dates, set_dates = ui.use_state({"start": start_date, "end": end_date}) + start = dates["start"] + end = dates["end"] + + # handler to filter the table + def handle_filter(filter_type, start, end, value, table): + if filter_type == "Date": + return table.where("Date >= start && Date < end") + else: + return table.where("Value=value") + + # memoize table operations and plots + filtered_table = ui.use_memo( + lambda start=start, end=end: handle_filter( + filter_type, start, end, value, table + ), + [filter_type, start, end, value, table], + ) + plot = ui.use_memo( + lambda: dx.line(filtered_table, x="Date", y="Row"), [filtered_table] + ) + + # This row will be the root layout for the dashboard + return ui.row( + control_panel(filter_type, set_filter_type, dates, set_dates, value, set_value), + ui.column( + ui.stack( + ui.panel(filtered_table, title="Filter table"), + ui.panel(table, title="Original table"), + active_item_index=0, + ), + ui.panel(plot, title="Plot"), + ), + ) + + +SECONDS_IN_DAY = 86400 +today = dh_now() +_table = time_table("PT1s").update_view( + [ + "Date=today.plusSeconds(SECONDS_IN_DAY*i)", + "Value=i%2==0 ? `A` : `B`", + "Row=i", + ] +) +_example_dashboard = ui.dashboard( + create_dashboard(today, today.plusSeconds(SECONDS_IN_DAY * 10), _table) +) + +_stocks = dx.data.stocks() +_dash_2x1 = ui.dashboard(ui.row(ui.panel("A", title="A"), ui.panel("B", title="B"))) +_dash_1x2 = ui.dashboard(ui.column(ui.panel("A", title="A"), ui.panel("B", title="B"))) +_dash_2x2 = ui.dashboard( + ui.row( + ui.column(ui.panel("A", title="A"), ui.panel("C", title="C")), + ui.column(ui.panel("B", title="B"), ui.panel("D", title="D")), + ) +) +_dash_3x1 = ui.dashboard( + ui.row(ui.panel("A", title="A"), ui.panel("B", title="B"), ui.panel("C", title="C")) +) +_dash_stack = ui.dashboard( + ui.stack( + ui.panel("A", title="A"), ui.panel("B", title="B"), ui.panel("C", title="C") + ) +) +_dash_stack_nested = ui.dashboard( + ui.stack( + ui.panel( + ui.tabs(ui.tab("A1 content", title="A1"), ui.tab("A2 content", title="A2")), + title="A", + ), + ui.panel( + ui.tabs(ui.tab("B1 content", title="B1"), ui.tab("B2 content", title="B2")), + title="B", + ), + ) +) +_dash_layout_stack = ui.dashboard( + ui.row( + ui.stack( + ui.panel("A", title="A"), ui.panel("B", title="B"), ui.panel("C", title="C") + ), + ui.panel("D", title="D"), + ui.panel("E", title="E"), + ) +) +_double_dash = ui.dashboard( + ui.row( + ui.panel( + "In this example dashboard, we show how one can make a dashboard with no headers, display UI panel on the left and display another dashboard in a panel on the right. This could be another home screen." + ), + ui.panel(_example_dashboard), + ), + show_headers=False, +) +# End of creating dashboards + + +from deephaven import ui +from typing import Callable + +simple_dashboards = {} +for i in range(0, 10): + simple_dashboards[f"Dashboard {i}"] = ui.dashboard( + ui.panel(ui.heading(f"Dashboard {i}")) + ) + +layout_dashboards = { + "Row split (2x1)": _dash_2x1, + "Column split (1x2)": _dash_1x2, + "2x2": _dash_2x2, + "3x1": _dash_3x1, + "Basic stack": _dash_stack, + "Nested stack": _dash_stack_nested, + "Stack in a layout": _dash_layout_stack, +} + +complex_dashboards = { + "Example Dashboard": _example_dashboard, + "Nested Dashboard": _double_dash, +} + + +@ui.component +def dashboard_list(dashboards, on_select: Callable[[any], None]): + return ui.flex( + map( + lambda k: ui.button( + k, on_press=lambda: on_select(dashboards[k]), variant="ghost" + ), + dashboards, + ), + direction="Column", + ) + + +@ui.component +def dashboard_menu(on_select: Callable[[any], None]): + return ui.accordion( + ui.disclosure( + "Simple dashboards", dashboard_list(simple_dashboards, on_select=on_select) + ), + ui.disclosure( + "Layout dashboards", dashboard_list(layout_dashboards, on_select=on_select) + ), + ui.disclosure( + "Complex dashboards", + dashboard_list(complex_dashboards, on_select=on_select), + ), + ) + + +@ui.component +def home_screen(): + active_dashboard, set_active_dashboard = ui.use_state(None) + + return ui.dashboard( + ui.row( + ui.column( + ui.panel(dashboard_menu(on_select=set_active_dashboard)), width=20 + ), + ui.panel( + ui.view( + active_dashboard, + key=None if active_dashboard is None else id(active_dashboard), + width="100%", + height="100%", + ) + ), + ), + show_headers=False, + ) + + +# Show the home screen nested within itself for funsies +complex_dashboards["Nested Homescreen"] = home_screen() + +ui_home_screen = home_screen() diff --git a/tests/ui_home_screen.spec.ts b/tests/ui_home_screen.spec.ts new file mode 100644 index 000000000..af813a98f --- /dev/null +++ b/tests/ui_home_screen.spec.ts @@ -0,0 +1,21 @@ +import { expect, test } from '@playwright/test'; +import { openPanel, gotoPage, SELECTORS, waitForLoad } from './utils'; + +test.describe('Homescreen', () => { + test('homescreen dashboard list visible', async ({ page }) => { + await gotoPage(page, ''); + await openPanel( + page, + 'ui_home_screen', + SELECTORS.REACT_PANEL_VISIBLE, + true + ); + + // Get the outer panel (first match) for screenshots + const outerPanel = page.locator(SELECTORS.REACT_PANEL_VISIBLE).first(); + await expect(outerPanel).toBeVisible(); + + // The nested dashboard should contain the dashboard list for the home screen + await expect(outerPanel.getByText('Simple dashboards')).toBeVisible(); + }); +}); From 5a46ecd493f47f2a5d8fcb1eb0bfff4c9c91c644 Mon Sep 17 00:00:00 2001 From: Mike Bender Date: Wed, 1 Apr 2026 20:39:50 -0400 Subject: [PATCH 02/15] Update types, remove duplicate types --- plugins/ui/src/js/package.json | 43 +++++++++++++-------------- plugins/ui/src/js/src/UIComponent.tsx | 4 --- plugins/ui/src/js/src/UIWidget.tsx | 6 +--- plugins/ui/src/js/src/index.ts | 8 ++--- 4 files changed, 24 insertions(+), 37 deletions(-) diff --git a/plugins/ui/src/js/package.json b/plugins/ui/src/js/package.json index ded929bf4..087106179 100644 --- a/plugins/ui/src/js/package.json +++ b/plugins/ui/src/js/package.json @@ -29,35 +29,34 @@ "update-dh-packages": "node ../../../../tools/update-dh-packages.mjs" }, "devDependencies": { + "@deephaven/test-utils": "^1.8.0", "@types/memoizee": "^0.4.5", - "@types/react": "^17.0.2", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "@types/react": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "dependencies": { - "@deephaven/chart": "^1.5.1", - "@deephaven/components": "^1.5.1", - "@deephaven/console": "^1.5.1", - "@deephaven/dashboard": "^1.5.1", - "@deephaven/dashboard-core-plugins": "^1.5.1", - "@deephaven/golden-layout": "^1.5.1", - "@deephaven/grid": "^1.3.0", + "@deephaven/components": "^1.17.0", + "@deephaven/console": "^1.17.0", + "@deephaven/dashboard": "^1.17.1", + "@deephaven/dashboard-core-plugins": "^1.17.1", + "@deephaven/golden-layout": "^1.17.1", + "@deephaven/grid": "^1.17.1", "@deephaven/icons": "^1.2.0", - "@deephaven/iris-grid": "^1.5.1", - "@deephaven/jsapi-bootstrap": "^1.5.1", - "@deephaven/jsapi-components": "^1.5.1", + "@deephaven/iris-grid": "^1.17.1", + "@deephaven/jsapi-bootstrap": "^1.17.0", + "@deephaven/jsapi-components": "^1.17.0", "@deephaven/jsapi-types": "^1.0.0-dev0.39.6", - "@deephaven/jsapi-utils": "^1.4.0", - "@deephaven/log": "^1.1.0", - "@deephaven/plugin": "^1.5.1", - "@deephaven/react-hooks": "^1.2.0", - "@deephaven/redux": "^1.5.1", - "@deephaven/test-utils": "^1.1.0", - "@deephaven/utils": "^1.1.0", + "@deephaven/jsapi-utils": "^1.16.0", + "@deephaven/log": "^1.8.0", + "@deephaven/plugin": "^1.17.1", + "@deephaven/react-hooks": "^1.14.0", + "@deephaven/redux": "^1.17.0", + "@deephaven/utils": "^1.10.0", "@fortawesome/react-fontawesome": "^0.2.0", "@internationalized/date": "^3.5.5", "classnames": "^2.5.1", diff --git a/plugins/ui/src/js/src/UIComponent.tsx b/plugins/ui/src/js/src/UIComponent.tsx index d2597ae45..e7754b3f2 100644 --- a/plugins/ui/src/js/src/UIComponent.tsx +++ b/plugins/ui/src/js/src/UIComponent.tsx @@ -5,15 +5,11 @@ import { usePersistentState, type WidgetComponentProps, } from '@deephaven/plugin'; -import { WidgetDescriptor } from '@deephaven/dashboard'; import { nanoid } from 'nanoid'; import { WidgetData, WidgetDataUpdate } from './widget/WidgetTypes'; import WidgetHandler from './widget/WidgetHandler'; type UIComponentProps = WidgetComponentProps & { - // TODO: We shouldn't need this, should be added to the WidgetComponentProps type - metadata?: WidgetDescriptor; - // Might be loading a URI resolved widget... uri?: UriVariableDescriptor; }; diff --git a/plugins/ui/src/js/src/UIWidget.tsx b/plugins/ui/src/js/src/UIWidget.tsx index a3feff652..9adba9b7a 100644 --- a/plugins/ui/src/js/src/UIWidget.tsx +++ b/plugins/ui/src/js/src/UIWidget.tsx @@ -1,13 +1,9 @@ import type { dh } from '@deephaven/jsapi-types'; import { type WidgetComponentProps } from '@deephaven/plugin'; -import { WidgetDescriptor } from '@deephaven/dashboard'; import UIComponent from './UIComponent'; import PortalPanel from './layout/PortalPanel'; -type UIWidgetProps = WidgetComponentProps & { - // TODO: We shouldn't need this, should be added to the WidgetComponentProps type - metadata?: WidgetDescriptor; -}; +type UIWidgetProps = WidgetComponentProps; export function UIWidget(props: UIWidgetProps): JSX.Element | null { const { metadata: widgetDescriptor } = props; diff --git a/plugins/ui/src/js/src/index.ts b/plugins/ui/src/js/src/index.ts index fdcf0d741..0da70be01 100644 --- a/plugins/ui/src/js/src/index.ts +++ b/plugins/ui/src/js/src/index.ts @@ -2,19 +2,15 @@ import { PluginType } from '@deephaven/plugin'; import { UIWidgetPlugin } from './UIWidgetPlugin'; import { DashboardPlugin } from './DashboardPlugin'; -// TODO: Remove local MultiPlugin type once @deephaven/plugin is updated -// to include it (see deephaven/web-client-ui composite-plugins branch) -const MULTI_PLUGIN = 'MultiPlugin' as const; - const UIDashboardPlugin = { name: '@deephaven/js-plugin-ui.DashboardPlugin', - type: PluginType.DASHBOARD_PLUGIN as string, + type: PluginType.DASHBOARD_PLUGIN, component: DashboardPlugin, }; const UIMultiPlugin = { name: '@deephaven/js-plugin-ui', - type: MULTI_PLUGIN as string, + type: PluginType.MULTI_PLUGIN, plugins: [UIWidgetPlugin, UIDashboardPlugin], }; From 9825b2aae092067a294a345f270ee7624284f91f Mon Sep 17 00:00:00 2001 From: Mike Bender Date: Wed, 1 Apr 2026 20:46:40 -0400 Subject: [PATCH 03/15] Cleanup after self-review --- plugins/ui/src/js/src/UIWidgetPlugin.ts | 6 ----- plugins/ui/src/js/src/index.ts | 6 +++++ .../ui/src/js/src/layout/NestedDashboard.tsx | 25 +------------------ .../js/src/widget/DashboardWidgetHandler.tsx | 5 +++- tests/ui_home_screen.spec.ts | 2 +- 5 files changed, 12 insertions(+), 32 deletions(-) diff --git a/plugins/ui/src/js/src/UIWidgetPlugin.ts b/plugins/ui/src/js/src/UIWidgetPlugin.ts index 7772af0a4..6de23bd2d 100644 --- a/plugins/ui/src/js/src/UIWidgetPlugin.ts +++ b/plugins/ui/src/js/src/UIWidgetPlugin.ts @@ -4,12 +4,6 @@ import type { dh } from '@deephaven/jsapi-types'; import { DASHBOARD_ELEMENT, WIDGET_ELEMENT } from './widget/WidgetUtils'; import PortalPanel from './layout/PortalPanel'; import UIWidget from './UIWidget'; -import styles from './styles.scss?inline'; - -// We need to inject the styles into the document when we're loaded... we only want to do this once. -const styleElement = document.createElement('style'); -styleElement.textContent = styles; -document.head.appendChild(styleElement); export const UIWidgetPlugin: WidgetPlugin = { name: '@deephaven/js-plugin-ui', diff --git a/plugins/ui/src/js/src/index.ts b/plugins/ui/src/js/src/index.ts index 0da70be01..ec3c08e3e 100644 --- a/plugins/ui/src/js/src/index.ts +++ b/plugins/ui/src/js/src/index.ts @@ -1,6 +1,12 @@ import { PluginType } from '@deephaven/plugin'; import { UIWidgetPlugin } from './UIWidgetPlugin'; import { DashboardPlugin } from './DashboardPlugin'; +import styles from './styles.scss?inline'; + +// We need to inject the styles into the document when we're loaded... we only want to do this once. +const styleElement = document.createElement('style'); +styleElement.textContent = styles; +document.head.appendChild(styleElement); const UIDashboardPlugin = { name: '@deephaven/js-plugin-ui.DashboardPlugin', diff --git a/plugins/ui/src/js/src/layout/NestedDashboard.tsx b/plugins/ui/src/js/src/layout/NestedDashboard.tsx index 2feac30ac..86ee5a10f 100644 --- a/plugins/ui/src/js/src/layout/NestedDashboard.tsx +++ b/plugins/ui/src/js/src/layout/NestedDashboard.tsx @@ -1,14 +1,8 @@ import React, { PropsWithChildren, useMemo, useState } from 'react'; -import { - Dashboard as DHCDashboard, - useDashboardPanel, - DashboardPluginComponentProps, - assertIsDashboardPluginProps, -} from '@deephaven/dashboard'; +import { Dashboard as DHCDashboard } from '@deephaven/dashboard'; import { useDashboardPlugins } from '@deephaven/plugin'; import NestedDashboardContent from './NestedDashboardContent'; import { ElementIdProps } from './LayoutUtils'; -import PortalPanel from './PortalPanel'; type NestedDashboardProps = PropsWithChildren & { /** @@ -17,22 +11,6 @@ type NestedDashboardProps = PropsWithChildren & { showHeaders?: boolean; }; -function NestedDashboardPlugin( - props: Partial -): JSX.Element | null { - assertIsDashboardPluginProps(props); - useDashboardPanel({ - dashboardProps: props, - componentName: PortalPanel.displayName, - component: PortalPanel, - - // We don't want these panels to be triggered by a widget opening, we want to control how it is opened later - supportedTypes: [], - }); - - return null; -} - /** * A dashboard that can be nested inside a panel. * Creates its own GoldenLayout instance and manages panels independently. @@ -57,7 +35,6 @@ function NestedDashboard({ layoutSettings={layoutSettings} > {plugins} - {layoutInitialized && ( {children} diff --git a/plugins/ui/src/js/src/widget/DashboardWidgetHandler.tsx b/plugins/ui/src/js/src/widget/DashboardWidgetHandler.tsx index 9d1c0cd4f..652856cce 100644 --- a/plugins/ui/src/js/src/widget/DashboardWidgetHandler.tsx +++ b/plugins/ui/src/js/src/widget/DashboardWidgetHandler.tsx @@ -45,7 +45,10 @@ function DashboardWidgetHandler({ const renderEmptyDocument = useCallback(() => { // Document hasn't been initialized yet. Display a loading spinner if applicable. - if (widgetDescriptor.type === WIDGET_ELEMENT) { + if ( + typeof widgetDescriptor === 'object' && + widgetDescriptor.type === WIDGET_ELEMENT + ) { // Rehydration. Mount ReactPanels for each panelId in the initial data // so loading spinners or widget errors are shown if (initialData?.panelIds != null && initialData.panelIds.length > 0) { diff --git a/tests/ui_home_screen.spec.ts b/tests/ui_home_screen.spec.ts index af813a98f..f725f85c9 100644 --- a/tests/ui_home_screen.spec.ts +++ b/tests/ui_home_screen.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from '@playwright/test'; -import { openPanel, gotoPage, SELECTORS, waitForLoad } from './utils'; +import { openPanel, gotoPage, SELECTORS } from './utils'; test.describe('Homescreen', () => { test('homescreen dashboard list visible', async ({ page }) => { From 6c136be2495d3d348798898f2632ca52c49640ad Mon Sep 17 00:00:00 2001 From: Mike Bender Date: Wed, 1 Apr 2026 22:25:13 -0400 Subject: [PATCH 04/15] Fix up failing unit tests --- plugins/ui/src/js/src/widget/WidgetHandler.tsx | 3 +-- plugins/ui/src/js/src/widget/WidgetTestUtils.ts | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/ui/src/js/src/widget/WidgetHandler.tsx b/plugins/ui/src/js/src/widget/WidgetHandler.tsx index c1191ed97..ff3a2969c 100644 --- a/plugins/ui/src/js/src/widget/WidgetHandler.tsx +++ b/plugins/ui/src/js/src/widget/WidgetHandler.tsx @@ -16,7 +16,7 @@ import { JSONRPCServer, JSONRPCServerAndClient, } from 'json-rpc-2.0'; -import { useLayoutManager, WidgetDescriptor } from '@deephaven/dashboard'; +import { WidgetDescriptor } from '@deephaven/dashboard'; import { UriVariableDescriptor, useWidget } from '@deephaven/jsapi-bootstrap'; import type { dh } from '@deephaven/jsapi-types'; import Log from '@deephaven/log'; @@ -45,7 +45,6 @@ import { transformNode, getComponentForElement, wrapCallable, - DASHBOARD_ELEMENT, } from './WidgetUtils'; import WidgetStatusContext, { WidgetStatus, diff --git a/plugins/ui/src/js/src/widget/WidgetTestUtils.ts b/plugins/ui/src/js/src/widget/WidgetTestUtils.ts index fa51e7098..b7c45b0a9 100644 --- a/plugins/ui/src/js/src/widget/WidgetTestUtils.ts +++ b/plugins/ui/src/js/src/widget/WidgetTestUtils.ts @@ -1,4 +1,5 @@ import { WidgetDescriptor } from '@deephaven/dashboard'; +// eslint-disable-next-line import/no-extraneous-dependencies import { TestUtils } from '@deephaven/test-utils'; import type { dh } from '@deephaven/jsapi-types'; import { Operation } from 'fast-json-patch'; From 01bcb7be01c5bc636c9267afaf6b4a0caf4085b3 Mon Sep 17 00:00:00 2001 From: mikebender Date: Mon, 6 Apr 2026 13:44:40 -0400 Subject: [PATCH 05/15] fix: update unit tests for WidgetPlugin changes - Add moduleNameMapper in jest.config.cjs to resolve React 18 from the plugin's local node_modules, fixing dual-React-instance errors - Mock usePersistentState in @deephaven/plugin mock to avoid FiberProvider dependency in tests - Update DocumentHandler test to reflect new behavior where non-layout children are rendered directly without ReactPanel wrapping --- plugins/ui/src/js/__mocks__/@deephaven/plugin.js | 4 ++++ plugins/ui/src/js/jest.config.cjs | 10 ++++++++++ plugins/ui/src/js/src/widget/DocumentHandler.test.tsx | 6 ++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/plugins/ui/src/js/__mocks__/@deephaven/plugin.js b/plugins/ui/src/js/__mocks__/@deephaven/plugin.js index e0ce22778..946fa84ee 100644 --- a/plugins/ui/src/js/__mocks__/@deephaven/plugin.js +++ b/plugins/ui/src/js/__mocks__/@deephaven/plugin.js @@ -1,8 +1,12 @@ // Mock @deephaven/plugin package +const React = require('react'); const PluginActual = jest.requireActual('@deephaven/plugin'); module.exports = { ...PluginActual, useDashboardPlugins: jest.fn(() => []), + // Mock usePersistentState to behave like useState. + // The real implementation requires FiberProvider which is internal to Dashboard. + usePersistentState: (initialState, _config) => React.useState(initialState), __esModule: true, }; diff --git a/plugins/ui/src/js/jest.config.cjs b/plugins/ui/src/js/jest.config.cjs index 221b5070f..cb7f206dc 100644 --- a/plugins/ui/src/js/jest.config.cjs +++ b/plugins/ui/src/js/jest.config.cjs @@ -1,7 +1,17 @@ +const path = require('path'); const baseConfig = require('../../../../jest.config.base.cjs'); const packageJson = require('./package'); module.exports = { ...baseConfig, displayName: packageJson.name, + moduleNameMapper: { + ...baseConfig.moduleNameMapper, + // Force all react imports to the local React 18 to avoid dual-instance issues + // with the root workspace's React 17. + '^react$': path.resolve(__dirname, 'node_modules/react'), + '^react/(.*)$': path.resolve(__dirname, 'node_modules/react/$1'), + '^react-dom$': path.resolve(__dirname, 'node_modules/react-dom'), + '^react-dom/(.*)$': path.resolve(__dirname, 'node_modules/react-dom/$1'), + }, }; diff --git a/plugins/ui/src/js/src/widget/DocumentHandler.test.tsx b/plugins/ui/src/js/src/widget/DocumentHandler.test.tsx index f45127afd..3d39b687a 100644 --- a/plugins/ui/src/js/src/widget/DocumentHandler.test.tsx +++ b/plugins/ui/src/js/src/widget/DocumentHandler.test.tsx @@ -72,10 +72,12 @@ it('should throw an error if the document mixes panel and non-panel elements', ( ); }); -it('should combine multiple single elements into one panel', () => { +it('should render multiple single elements directly without wrapping in a panel', () => { const children = makeDocument([makeElement('foo'), makeElement('bar')]); render(makeDocumentHandler({ children })); - expect(mockReactPanel).toHaveBeenCalledTimes(1); + // When not nested (no PanelIdContext), non-layout children are rendered directly + // without being wrapped in a ReactPanel (WidgetPlugin handles the panel) + expect(mockReactPanel).toHaveBeenCalledTimes(0); }); it('should render multiple panels', () => { From 1ec6d324ad382f605fe9dde28db29a513d91427c Mon Sep 17 00:00:00 2001 From: mikebender Date: Thu, 9 Apr 2026 10:07:19 -0400 Subject: [PATCH 06/15] Update package-lock.json --- package-lock.json | 727 ++++++++++++++++++++++++++-------------------- 1 file changed, 404 insertions(+), 323 deletions(-) diff --git a/package-lock.json b/package-lock.json index c2a355a0b..54ac048d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4798,6 +4798,7 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/@deephaven/test-utils/-/test-utils-1.8.0.tgz", "integrity": "sha512-Lcan+J/pV1DvqJJ91ohnWzClQh4HkFpW0CsZD5DCzyCUh3LV95D14uaY54s+jFoRTOeSbFB91eSIWb9Yp1FIFA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=16" @@ -4839,6 +4840,20 @@ "react-dom": ">=16.8.0" } }, + "node_modules/@dnd-kit/modifiers": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-9.0.0.tgz", + "integrity": "sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==", + "license": "MIT", + "dependencies": { + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.3.0", + "react": ">=16.8.0" + } + }, "node_modules/@dnd-kit/sortable": { "version": "7.0.2", "license": "MIT", @@ -11875,6 +11890,23 @@ "@swc/counter": "^0.1.3" } }, + "node_modules/@tanstack/react-virtual": { + "version": "3.13.23", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.23.tgz", + "integrity": "sha512-XnMRnHQ23piOVj2bzJqHrRrLg4r+F86fuBcwteKfbIjJrtGxb4z7tIvPVAe4B+4UVwo9G4Giuz5fmapcrnZ0OQ==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.13.23" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/@tanstack/virtual-core": { "version": "3.13.23", "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.23.tgz", @@ -32667,20 +32699,6 @@ "react-dom": ">=18.0.0" } }, - "plugins/plotly-express/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/@deephaven/iris-grid/node_modules/@dnd-kit/modifiers": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-9.0.0.tgz", - "integrity": "sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==", - "license": "MIT", - "dependencies": { - "@dnd-kit/utilities": "^3.2.2", - "tslib": "^2.0.0" - }, - "peerDependencies": { - "@dnd-kit/core": "^6.3.0", - "react": ">=16.8.0" - } - }, "plugins/plotly-express/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/@deephaven/iris-grid/node_modules/@dnd-kit/sortable": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz", @@ -32735,23 +32753,6 @@ } } }, - "plugins/plotly-express/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/@deephaven/iris-grid/node_modules/@tanstack/react-virtual": { - "version": "3.13.23", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.23.tgz", - "integrity": "sha512-XnMRnHQ23piOVj2bzJqHrRrLg4r+F86fuBcwteKfbIjJrtGxb4z7tIvPVAe4B+4UVwo9G4Giuz5fmapcrnZ0OQ==", - "license": "MIT", - "dependencies": { - "@tanstack/virtual-core": "3.13.23" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "plugins/plotly-express/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/@deephaven/iris-grid/node_modules/redux": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", @@ -33140,20 +33141,6 @@ "react": ">=16.8.0" } }, - "plugins/plotly-express/src/js/node_modules/@deephaven/plugin/node_modules/@deephaven/iris-grid/node_modules/@dnd-kit/modifiers": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-9.0.0.tgz", - "integrity": "sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==", - "license": "MIT", - "dependencies": { - "@dnd-kit/utilities": "^3.2.2", - "tslib": "^2.0.0" - }, - "peerDependencies": { - "@dnd-kit/core": "^6.3.0", - "react": ">=16.8.0" - } - }, "plugins/plotly-express/src/js/node_modules/@deephaven/plugin/node_modules/@deephaven/iris-grid/node_modules/@dnd-kit/sortable": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz", @@ -33208,23 +33195,6 @@ } } }, - "plugins/plotly-express/src/js/node_modules/@deephaven/plugin/node_modules/@deephaven/iris-grid/node_modules/@tanstack/react-virtual": { - "version": "3.13.23", - "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.23.tgz", - "integrity": "sha512-XnMRnHQ23piOVj2bzJqHrRrLg4r+F86fuBcwteKfbIjJrtGxb4z7tIvPVAe4B+4UVwo9G4Giuz5fmapcrnZ0OQ==", - "license": "MIT", - "dependencies": { - "@tanstack/virtual-core": "3.13.23" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, "plugins/plotly-express/src/js/node_modules/@deephaven/plugin/node_modules/@deephaven/react-hooks": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/@deephaven/react-hooks/-/react-hooks-1.14.0.tgz", @@ -35028,25 +34998,23 @@ "version": "0.34.0", "license": "Apache-2.0", "dependencies": { - "@deephaven/chart": "^1.5.1", - "@deephaven/components": "^1.5.1", - "@deephaven/console": "^1.5.1", - "@deephaven/dashboard": "^1.5.1", - "@deephaven/dashboard-core-plugins": "^1.5.1", - "@deephaven/golden-layout": "^1.5.1", - "@deephaven/grid": "^1.3.0", + "@deephaven/components": "^1.17.0", + "@deephaven/console": "^1.17.0", + "@deephaven/dashboard": "^1.17.1", + "@deephaven/dashboard-core-plugins": "^1.17.1", + "@deephaven/golden-layout": "^1.17.1", + "@deephaven/grid": "^1.17.1", "@deephaven/icons": "^1.2.0", - "@deephaven/iris-grid": "^1.5.1", - "@deephaven/jsapi-bootstrap": "^1.5.1", - "@deephaven/jsapi-components": "^1.5.1", + "@deephaven/iris-grid": "^1.17.1", + "@deephaven/jsapi-bootstrap": "^1.17.0", + "@deephaven/jsapi-components": "^1.17.0", "@deephaven/jsapi-types": "^1.0.0-dev0.39.6", - "@deephaven/jsapi-utils": "^1.4.0", - "@deephaven/log": "^1.1.0", - "@deephaven/plugin": "^1.5.1", - "@deephaven/react-hooks": "^1.2.0", - "@deephaven/redux": "^1.5.1", - "@deephaven/test-utils": "^1.1.0", - "@deephaven/utils": "^1.1.0", + "@deephaven/jsapi-utils": "^1.16.0", + "@deephaven/log": "^1.8.0", + "@deephaven/plugin": "^1.17.1", + "@deephaven/react-hooks": "^1.14.0", + "@deephaven/redux": "^1.17.0", + "@deephaven/utils": "^1.10.0", "@fortawesome/react-fontawesome": "^0.2.0", "@internationalized/date": "^3.5.5", "classnames": "^2.5.1", @@ -35060,36 +35028,36 @@ "remark-math": "^5.1.1" }, "devDependencies": { + "@deephaven/test-utils": "^1.8.0", "@types/memoizee": "^0.4.5", - "@types/react": "^17.0.2", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "@types/react": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, "plugins/ui/src/js/node_modules/@deephaven/chart": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@deephaven/chart/-/chart-1.5.1.tgz", - "integrity": "sha512-PgqLsK3b7KBvpymOSscvmW5K//ZTWpjG13vgrMW7qIVQUAwwSNnnvsf5o5ahJnMq6olSMnoOFg2zBrAMyOvTaw==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@deephaven/chart/-/chart-1.17.0.tgz", + "integrity": "sha512-5HG0YfZrMali/6NVtKidpDYO+vOdLq2piWiwqHZf2XApdhwrn502I8xj1w2KsSLhbMJH8X6HFRMsqLLQjDZvbA==", + "license": "Apache-2.0", "dependencies": { - "@deephaven/components": "^1.5.1", + "@deephaven/components": "^1.17.0", "@deephaven/icons": "^1.2.0", - "@deephaven/jsapi-types": "^1.0.0-dev0.39.4", - "@deephaven/jsapi-utils": "^1.4.0", - "@deephaven/log": "^1.1.0", - "@deephaven/react-hooks": "^1.2.0", - "@deephaven/utils": "^1.1.0", + "@deephaven/jsapi-types": "^1.0.0-dev0.40.4", + "@deephaven/jsapi-utils": "^1.16.0", + "@deephaven/log": "^1.8.0", + "@deephaven/react-hooks": "^1.14.0", + "@deephaven/utils": "^1.10.0", "buffer": "^6.0.3", "fast-deep-equal": "^3.1.3", - "lodash.debounce": "^4.0.8", - "lodash.set": "^4.3.2", + "lodash": "^4.17.21", "memoize-one": "^5.1.1", "memoizee": "^0.4.15", - "plotly.js": "3.1.0-rc.0", - "prop-types": "^15.7.2", + "plotly.js": "3.1.0", "react-plotly.js": "^2.6.0" }, "engines": { @@ -35100,17 +35068,21 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/components": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@deephaven/components/-/components-1.5.1.tgz", - "integrity": "sha512-AgShjar3dMqjeqqo7im76RoCeoMq9AbGWRp/agO+mi6Sw9Jg2lBmwnV0FPVmkgvp3JbBApINmD6U0WDMLCNWUw==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@deephaven/components/-/components-1.17.0.tgz", + "integrity": "sha512-0H/W0q3iH07rKvS/Ev3OLLfeAQtZi/sujuZL+MnQInPJTX3rNHb8XcwAKI5bI/u5a/+PvGkNswZcS3njvKxJ0Q==", + "license": "Apache-2.0", "dependencies": { "@adobe/react-spectrum": "3.38.0", "@deephaven/icons": "^1.2.0", - "@deephaven/log": "^1.1.0", - "@deephaven/react-hooks": "^1.2.0", - "@deephaven/utils": "^1.1.0", + "@deephaven/log": "^1.8.0", + "@deephaven/react-hooks": "^1.14.0", + "@deephaven/utils": "^1.10.0", + "@fontsource/fira-mono": "5.0.13", + "@fontsource/fira-sans": "5.0.20", "@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/react-fontawesome": "^0.2.0", + "@hello-pangea/dnd": "^18.0.1", "@internationalized/date": "^3.5.5", "@react-spectrum/theme-default": "^3.5.1", "@react-spectrum/toast": "^3.0.0-beta.16", @@ -35128,12 +35100,10 @@ "memoizee": "^0.4.15", "nanoid": "^5.0.7", "popper.js": "^1.16.1", - "prop-types": "^15.7.2", - "react-beautiful-dnd": "^13.1.0", "react-reverse-portal": "^2.3.0", "react-transition-group": "^4.4.2", - "react-virtualized-auto-sizer": "1.0.6", - "react-window": "^1.8.6" + "react-virtualized-auto-sizer": "1.0.7", + "react-window": "^1.8.7" }, "engines": { "node": ">=10" @@ -35155,21 +35125,22 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/console": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@deephaven/console/-/console-1.5.1.tgz", - "integrity": "sha512-R7rBJrDtunGOuBMnGmERuHXV8rGV0QiKPAI+zZFMMgbNeq5gbEHhvGyfsO1vmXxwIdQoCWgsPSrYv9nDVc+NNQ==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@deephaven/console/-/console-1.17.0.tgz", + "integrity": "sha512-6ppKiIEauOsaoQqNVvnuy/sAUQ08jlt1oqpA+zDGExa4johJQznGtw33OlTCDpmOINui8JEQy8XRdRne/ND9tw==", + "license": "Apache-2.0", "dependencies": { "@astral-sh/ruff-wasm-web": "0.6.4", - "@deephaven/chart": "^1.5.1", - "@deephaven/components": "^1.5.1", + "@deephaven/chart": "^1.17.0", + "@deephaven/components": "^1.17.0", "@deephaven/icons": "^1.2.0", - "@deephaven/jsapi-bootstrap": "^1.5.1", - "@deephaven/jsapi-types": "^1.0.0-dev0.39.4", - "@deephaven/jsapi-utils": "^1.4.0", - "@deephaven/log": "^1.1.0", - "@deephaven/react-hooks": "^1.2.0", - "@deephaven/storage": "^1.1.0", - "@deephaven/utils": "^1.1.0", + "@deephaven/jsapi-bootstrap": "^1.17.0", + "@deephaven/jsapi-types": "^1.0.0-dev0.40.4", + "@deephaven/jsapi-utils": "^1.16.0", + "@deephaven/log": "^1.8.0", + "@deephaven/react-hooks": "^1.14.0", + "@deephaven/storage": "^1.8.0", + "@deephaven/utils": "^1.10.0", "@fortawesome/react-fontawesome": "^0.2.0", "classnames": "^2.3.1", "linkifyjs": "^4.1.0", @@ -35181,7 +35152,6 @@ "nanoid": "^5.0.7", "papaparse": "5.3.2", "popper.js": "^1.16.1", - "prop-types": "^15.7.2", "shell-quote": "^1.7.2" }, "engines": { @@ -35192,33 +35162,18 @@ "react-dom": ">=16.8.0" } }, - "plugins/ui/src/js/node_modules/@deephaven/console/node_modules/@deephaven/storage": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@deephaven/storage/-/storage-1.1.0.tgz", - "integrity": "sha512-H/ggOTHagkO8ghvbqllS87wH/My4Ob6dppP8UjakoOax560VOXUh0d2w23OHW97PvoeVK+MJlNXnLahJQtgVqg==", - "dependencies": { - "@deephaven/filters": "^1.1.0", - "@deephaven/log": "^1.1.0", - "lodash.throttle": "^4.1.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, "plugins/ui/src/js/node_modules/@deephaven/dashboard": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@deephaven/dashboard/-/dashboard-1.5.1.tgz", - "integrity": "sha512-BMEWQSdpGiHVhLLsFtRGw5HLfGnZOR4zoZIDGCB6byxqPhvFKLSJ3zWk6bBahJ54hWGrLmkUZKdZ4e/BroF2wQ==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@deephaven/dashboard/-/dashboard-1.17.1.tgz", + "integrity": "sha512-ToEAhv9Im/kumvv+OLJgQO27rc+jRJGoNbej4rbRRU2PQGjKh9+eJlYMA4kHM4jSQrM9EJUtmF5MAoU9fwwyPA==", + "license": "Apache-2.0", "dependencies": { - "@deephaven/components": "^1.5.1", - "@deephaven/golden-layout": "^1.5.1", - "@deephaven/log": "^1.1.0", - "@deephaven/react-hooks": "^1.2.0", - "@deephaven/redux": "^1.5.1", - "@deephaven/utils": "^1.1.0", + "@deephaven/components": "^1.17.0", + "@deephaven/golden-layout": "^1.17.1", + "@deephaven/log": "^1.8.0", + "@deephaven/react-hooks": "^1.14.0", + "@deephaven/redux": "^1.17.0", + "@deephaven/utils": "^1.10.0", "classnames": "^2.3.1", "fast-deep-equal": "^3.1.3", "lodash.ismatch": "^4.1.1", @@ -35237,30 +35192,31 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/dashboard-core-plugins": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@deephaven/dashboard-core-plugins/-/dashboard-core-plugins-1.5.1.tgz", - "integrity": "sha512-UN3e7LtxP3DlP2FnqJ1eIHgI031hlOCfZlUmBfhUeqZt/aQvVXo1ajKcmYbcG8ECzsu4YmWJD/ISC4lhpIYKHw==", - "dependencies": { - "@deephaven/chart": "^1.5.1", - "@deephaven/components": "^1.5.1", - "@deephaven/console": "^1.5.1", - "@deephaven/dashboard": "^1.5.1", - "@deephaven/file-explorer": "^1.5.1", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@deephaven/dashboard-core-plugins/-/dashboard-core-plugins-1.17.1.tgz", + "integrity": "sha512-KVDrAnFUANZqJ0NKKuQgsjJ7a2PlP02TEzbAfcQ2gGwxI8O4mVm4wvrnTI5U549G7H1XvbSuPnA+R9vGJfiRyQ==", + "license": "Apache-2.0", + "dependencies": { + "@deephaven/chart": "^1.17.0", + "@deephaven/components": "^1.17.0", + "@deephaven/console": "^1.17.0", + "@deephaven/dashboard": "^1.17.1", + "@deephaven/file-explorer": "^1.17.0", "@deephaven/filters": "^1.1.0", - "@deephaven/golden-layout": "^1.5.1", - "@deephaven/grid": "^1.3.0", + "@deephaven/golden-layout": "^1.17.1", + "@deephaven/grid": "^1.17.1", "@deephaven/icons": "^1.2.0", - "@deephaven/iris-grid": "^1.5.1", - "@deephaven/jsapi-bootstrap": "^1.5.1", - "@deephaven/jsapi-components": "^1.5.1", - "@deephaven/jsapi-types": "^1.0.0-dev0.39.4", - "@deephaven/jsapi-utils": "^1.4.0", - "@deephaven/log": "^1.1.0", - "@deephaven/plugin": "^1.5.1", - "@deephaven/react-hooks": "^1.2.0", - "@deephaven/redux": "^1.5.1", - "@deephaven/storage": "^1.1.0", - "@deephaven/utils": "^1.1.0", + "@deephaven/iris-grid": "^1.17.1", + "@deephaven/jsapi-bootstrap": "^1.17.0", + "@deephaven/jsapi-components": "^1.17.0", + "@deephaven/jsapi-types": "^1.0.0-dev0.40.4", + "@deephaven/jsapi-utils": "^1.16.0", + "@deephaven/log": "^1.8.0", + "@deephaven/plugin": "^1.17.1", + "@deephaven/react-hooks": "^1.14.0", + "@deephaven/redux": "^1.17.0", + "@deephaven/storage": "^1.8.0", + "@deephaven/utils": "^1.10.0", "@fortawesome/react-fontawesome": "^0.2.0", "classnames": "^2.3.1", "fast-deep-equal": "^3.1.3", @@ -35287,45 +35243,6 @@ "react-redux": "^7.2.4" } }, - "plugins/ui/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/@deephaven/file-explorer": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@deephaven/file-explorer/-/file-explorer-1.5.1.tgz", - "integrity": "sha512-slx7B6vfdxrSK0hRwMSTIhR7tuaP+fsQFJtTKWO0DHKpbeiGTJ49QRcWEO5TSJfIGkFsp5rQdmyz9+7nKZ6bIw==", - "dependencies": { - "@deephaven/components": "^1.5.1", - "@deephaven/icons": "^1.2.0", - "@deephaven/log": "^1.1.0", - "@deephaven/storage": "^1.1.0", - "@deephaven/utils": "^1.1.0", - "@fortawesome/fontawesome-svg-core": "^6.2.1", - "@fortawesome/react-fontawesome": "^0.2.0", - "classnames": "^2.3.1", - "lodash.throttle": "^4.1.1", - "prop-types": "^15.7.2" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "plugins/ui/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/@deephaven/storage": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@deephaven/storage/-/storage-1.1.0.tgz", - "integrity": "sha512-H/ggOTHagkO8ghvbqllS87wH/My4Ob6dppP8UjakoOax560VOXUh0d2w23OHW97PvoeVK+MJlNXnLahJQtgVqg==", - "dependencies": { - "@deephaven/filters": "^1.1.0", - "@deephaven/log": "^1.1.0", - "lodash.throttle": "^4.1.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, "plugins/ui/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/rehype-mathjax": { "version": "4.0.3", "license": "MIT", @@ -35344,20 +35261,45 @@ "url": "https://opencollective.com/unified" } }, - "plugins/ui/src/js/node_modules/@deephaven/filters": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@deephaven/filters/-/filters-1.1.0.tgz", - "integrity": "sha512-SMWKYT8aFtZ/CyVUtUiF1/RPQGl4Y6dvNG43KvmIMKKMXYqhliKD291aynYSl7C8IafkHNzdDtdAZPgPXLoOWA==", - "engines": { - "node": ">=16" - } - }, - "plugins/ui/src/js/node_modules/@deephaven/golden-layout": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@deephaven/golden-layout/-/golden-layout-1.5.1.tgz", - "integrity": "sha512-aGXb/7JRGKJMfRyoR3K1bF2yxxoAUZNaGs7DxxZoPVYdH3OA82GMaJESmBGzmHuS82blfwkHtCSWt6nBXA8vhg==", - "dependencies": { - "@deephaven/components": "^1.5.1", + "plugins/ui/src/js/node_modules/@deephaven/file-explorer": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@deephaven/file-explorer/-/file-explorer-1.17.0.tgz", + "integrity": "sha512-bFMN3oQ6RikiPskD9aXoEyCN0voej8r8Zl6jgUzgym8HCFegSt5nJccBxgWmC3LppuZIgDMQqqjcfxPgfKLwRw==", + "license": "Apache-2.0", + "dependencies": { + "@deephaven/components": "^1.17.0", + "@deephaven/icons": "^1.2.0", + "@deephaven/log": "^1.8.0", + "@deephaven/storage": "^1.8.0", + "@deephaven/utils": "^1.10.0", + "@fortawesome/fontawesome-svg-core": "^6.2.1", + "@fortawesome/react-fontawesome": "^0.2.0", + "classnames": "^2.3.1", + "lodash.throttle": "^4.1.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "plugins/ui/src/js/node_modules/@deephaven/filters": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@deephaven/filters/-/filters-1.1.0.tgz", + "integrity": "sha512-SMWKYT8aFtZ/CyVUtUiF1/RPQGl4Y6dvNG43KvmIMKKMXYqhliKD291aynYSl7C8IafkHNzdDtdAZPgPXLoOWA==", + "license": "Apache-2.0", + "engines": { + "node": ">=16" + } + }, + "plugins/ui/src/js/node_modules/@deephaven/golden-layout": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@deephaven/golden-layout/-/golden-layout-1.17.1.tgz", + "integrity": "sha512-lnA87WSFcFoceK7DtsxNqKjEYCF7L427VxtMdMR7xU/tsTJUQnlT5MNR9BV/2Ybz8AR8Kh1qQv/3EmY1vlHGmA==", + "license": "Apache-2.0", + "dependencies": { + "@deephaven/components": "^1.17.0", "jquery": "^3.6.0", "nanoid": "^5.0.7" }, @@ -35367,19 +35309,19 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/grid": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@deephaven/grid/-/grid-1.3.0.tgz", - "integrity": "sha512-k5Te+dBqSyXW0TaV2rEYOD0UShIsvvIFsYUqQNadDJ7UA1QRgpDfRy7+KzV5BLnfdu57zDLqTpPFiPyjK058GA==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@deephaven/grid/-/grid-1.17.1.tgz", + "integrity": "sha512-F0G5kjOXhDBZulIHS7z70wH4gfwC0wi57InGKfB2gxN8L8WKfuR2LwGDQuC40avWZyB90jf1ihEwaUMh8Mp7fw==", + "license": "Apache-2.0", "dependencies": { - "@deephaven/utils": "^1.1.0", + "@deephaven/utils": "^1.10.0", "classnames": "^2.3.1", "color-convert": "^2.0.1", "event-target-shim": "^6.0.2", "linkifyjs": "^4.1.0", "lodash.clamp": "^4.0.3", "memoize-one": "^5.1.1", - "memoizee": "^0.4.15", - "prop-types": "^15.7.2" + "memoizee": "^0.4.15" }, "engines": { "node": ">=16" @@ -35401,26 +35343,30 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/iris-grid": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@deephaven/iris-grid/-/iris-grid-1.5.1.tgz", - "integrity": "sha512-MN0yUR0F+okQvSAlteh5vYFBeSyzmojmnh1DRvBUIkKLj4T/s3uUFErgyYG5hcY6R6yyfADedU3PUED65wcZOQ==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@deephaven/iris-grid/-/iris-grid-1.17.1.tgz", + "integrity": "sha512-Vt8MawNYClW+D9oFYgT1e2INLPuQMuGDULv70XrDyEySxJYc67f+8Wxoe41zIrlwvi2JX6KJbEGPsZHk2NdYiw==", + "license": "Apache-2.0", "dependencies": { - "@deephaven/components": "^1.5.1", - "@deephaven/console": "^1.5.1", + "@deephaven/components": "^1.17.0", + "@deephaven/console": "^1.17.0", "@deephaven/filters": "^1.1.0", - "@deephaven/grid": "^1.3.0", + "@deephaven/grid": "^1.17.1", "@deephaven/icons": "^1.2.0", - "@deephaven/jsapi-components": "^1.5.1", - "@deephaven/jsapi-types": "^1.0.0-dev0.39.4", - "@deephaven/jsapi-utils": "^1.4.0", - "@deephaven/log": "^1.1.0", - "@deephaven/react-hooks": "^1.2.0", - "@deephaven/storage": "^1.1.0", - "@deephaven/utils": "^1.1.0", + "@deephaven/jsapi-components": "^1.17.0", + "@deephaven/jsapi-types": "^1.0.0-dev0.40.4", + "@deephaven/jsapi-utils": "^1.16.0", + "@deephaven/log": "^1.8.0", + "@deephaven/react-hooks": "^1.14.0", + "@deephaven/storage": "^1.8.0", + "@deephaven/utils": "^1.10.0", "@dnd-kit/core": "^6.1.0", - "@dnd-kit/sortable": "^7.0.2", + "@dnd-kit/modifiers": "^9.0.0", + "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", "@fortawesome/react-fontawesome": "^0.2.0", + "@hello-pangea/dnd": "^18.0.1", + "@tanstack/react-virtual": "^3.13.12", "classnames": "^2.3.1", "fast-deep-equal": "^3.1.3", "lodash.clamp": "^4.0.3", @@ -35430,44 +35376,27 @@ "memoizee": "^0.4.15", "monaco-editor": "^0.43.0", "nanoid": "^5.0.7", - "prop-types": "^15.7.2", - "react-beautiful-dnd": "^13.1.0", "react-transition-group": "^4.4.2" }, "engines": { "node": ">=10" }, "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "plugins/ui/src/js/node_modules/@deephaven/iris-grid/node_modules/@deephaven/storage": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@deephaven/storage/-/storage-1.1.0.tgz", - "integrity": "sha512-H/ggOTHagkO8ghvbqllS87wH/My4Ob6dppP8UjakoOax560VOXUh0d2w23OHW97PvoeVK+MJlNXnLahJQtgVqg==", - "dependencies": { - "@deephaven/filters": "^1.1.0", - "@deephaven/log": "^1.1.0", - "lodash.throttle": "^4.1.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "react": ">=16.8.0" + "react": ">=18.0.0", + "react-dom": ">=18.0.0" } }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-bootstrap": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@deephaven/jsapi-bootstrap/-/jsapi-bootstrap-1.5.1.tgz", - "integrity": "sha512-KKLpjChMf97QOAAac46owp6NLutcLqOGhb49ZbFb4rb4a+J4NKIaUO0EB2FUiYnrp4SNVri3izhIJXfN5J7OdA==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-bootstrap/-/jsapi-bootstrap-1.17.0.tgz", + "integrity": "sha512-0ffPtsrq0oTOzfjwG/JYx7gMVIrJ0125Axk0yDt1/ozOnPzVMSN9MpK9EtUyGxgckWCdCwvQ8XYgkYtliNmHPw==", + "license": "Apache-2.0", "dependencies": { - "@deephaven/components": "^1.5.1", - "@deephaven/jsapi-types": "^1.0.0-dev0.39.4", - "@deephaven/log": "^1.1.0", - "@deephaven/react-hooks": "^1.2.0", - "@deephaven/utils": "^1.1.0" + "@deephaven/components": "^1.17.0", + "@deephaven/jsapi-types": "^1.0.0-dev0.40.4", + "@deephaven/log": "^1.8.0", + "@deephaven/react-hooks": "^1.14.0", + "@deephaven/utils": "^1.10.0" }, "engines": { "node": ">=16" @@ -35477,22 +35406,22 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-components": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@deephaven/jsapi-components/-/jsapi-components-1.5.1.tgz", - "integrity": "sha512-KJDEbnlTsxeroTzFdnlZ+Y8alHqajI56/U+KvQS1K5zk7B+pb5QS+ZHddcn5ndklUUnHOJd+2TmHjlT0LgyRYQ==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-components/-/jsapi-components-1.17.0.tgz", + "integrity": "sha512-am7GSuDiAa2L8+otndrK3wQ5HIZOiSnxBf/ytIEZo9J+bpuCuDH31J5E1GrXWNnRjKxEqSACwk7e5+fCysJXbw==", + "license": "Apache-2.0", "dependencies": { - "@deephaven/components": "^1.5.1", - "@deephaven/jsapi-bootstrap": "^1.5.1", - "@deephaven/jsapi-types": "^1.0.0-dev0.39.4", - "@deephaven/jsapi-utils": "^1.4.0", - "@deephaven/log": "^1.1.0", - "@deephaven/react-hooks": "^1.2.0", - "@deephaven/utils": "^1.1.0", + "@deephaven/components": "^1.17.0", + "@deephaven/jsapi-bootstrap": "^1.17.0", + "@deephaven/jsapi-types": "^1.0.0-dev0.40.4", + "@deephaven/jsapi-utils": "^1.16.0", + "@deephaven/log": "^1.8.0", + "@deephaven/react-hooks": "^1.14.0", + "@deephaven/utils": "^1.10.0", "@types/js-cookie": "^3.0.3", "classnames": "^2.3.2", "js-cookie": "^3.0.5", - "lodash.debounce": "^4.0.8", - "prop-types": "^15.8.1" + "lodash.debounce": "^4.0.8" }, "engines": { "node": ">=16" @@ -35502,19 +35431,21 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-types": { - "version": "1.0.0-dev0.39.6", - "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.39.6.tgz", - "integrity": "sha512-kv8P1orTjj1P1E419mtzpdsaTqSbzceq4X6X0XWeaHAQvTfO8A5fw+47hQx2bLNM6JL5AlP7ClrA4HfdLLH2Gw==" + "version": "1.0.0-dev0.40.9", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.40.9.tgz", + "integrity": "sha512-NwMxFmNCnRV4/2+MdN/8vUGiEtXFgL1K/+iXTKKvi+Brje5JHOSCn2miCKR9tAn0LNb/UdmJq+DSIZqvz8cU/Q==", + "license": "Apache-2.0" }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@deephaven/jsapi-utils/-/jsapi-utils-1.4.0.tgz", - "integrity": "sha512-6MEu68rsCrS9SiCSwdvPH20CcFxdeUUYdzCGO/A4DEb3eYOWpxPb/KCIi8ZQwttuekvh9oIHQyCWLmDGKJzn8g==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-utils/-/jsapi-utils-1.16.0.tgz", + "integrity": "sha512-lyMDgxmb7v2GDlm1Ksf4S037QuWUhpOMKtnHZoEuKKIthcd6WejsNP+S8U2iRCYSJiJ1jEpTAVMrrS2CM4ZC7w==", + "license": "Apache-2.0", "dependencies": { "@deephaven/filters": "^1.1.0", - "@deephaven/jsapi-types": "^1.0.0-dev0.39.4", - "@deephaven/log": "^1.1.0", - "@deephaven/utils": "^1.1.0", + "@deephaven/jsapi-types": "^1.0.0-dev0.40.4", + "@deephaven/log": "^1.8.0", + "@deephaven/utils": "^1.10.0", "lodash.clamp": "^4.0.3", "nanoid": "^5.0.7" }, @@ -35523,30 +35454,34 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/log": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@deephaven/log/-/log-1.1.0.tgz", - "integrity": "sha512-07Ww5o1iA9M65KoyHTfHTmCnzGIa/5OVP29pyP+FGmaXXMgujdvFRPfLHki0EeW92WOttXfK51kjDyzkBcs11Q==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@deephaven/log/-/log-1.8.0.tgz", + "integrity": "sha512-gzp6/7qW4W8Re+DLSaG33KEQJ30OrrNq3cNQA8fUeXQrabSNOIsyeVOaerQ/57c4zWhWVKamplax0LIYRsmDiw==", + "license": "Apache-2.0", "dependencies": { "event-target-shim": "^6.0.2", - "jszip": "^3.10.1" + "jszip": "^3.10.1", + "safe-stable-stringify": "^2.5.0" }, "engines": { "node": ">=16" } }, "plugins/ui/src/js/node_modules/@deephaven/plugin": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@deephaven/plugin/-/plugin-1.5.1.tgz", - "integrity": "sha512-0xprRa9gzsiwgvoqananeuFE1cSofEpdBggG+/F6kh2IYopavVx9cl1KDjMvLeKomVANANGkfntIi46INKx3jA==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@deephaven/plugin/-/plugin-1.17.1.tgz", + "integrity": "sha512-szVeSG7yL7eKLQnAwlDOChzmlzdbwgUeF9iIOCeaOSYA9t4sXgT8FN/f+68dyL56/AC0OYpc90lp/5buedCuXQ==", + "license": "Apache-2.0", "dependencies": { - "@deephaven/components": "^1.5.1", - "@deephaven/golden-layout": "^1.5.1", - "@deephaven/grid": "^1.3.0", + "@deephaven/components": "^1.17.0", + "@deephaven/dashboard": "^1.17.1", + "@deephaven/golden-layout": "^1.17.1", + "@deephaven/grid": "^1.17.1", "@deephaven/icons": "^1.2.0", - "@deephaven/iris-grid": "^1.5.1", - "@deephaven/jsapi-types": "^1.0.0-dev0.39.4", - "@deephaven/log": "^1.1.0", - "@deephaven/react-hooks": "^1.2.0", + "@deephaven/iris-grid": "^1.17.1", + "@deephaven/jsapi-types": "^1.0.0-dev0.40.4", + "@deephaven/log": "^1.8.0", + "@deephaven/react-hooks": "^1.14.0", "@fortawesome/fontawesome-common-types": "^6.1.1", "@fortawesome/react-fontawesome": "^0.2.0", "nanoid": "^5.0.7" @@ -35559,13 +35494,14 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/react-hooks": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@deephaven/react-hooks/-/react-hooks-1.2.0.tgz", - "integrity": "sha512-8CoWWvNv1xNBJBe6HxK2Mnd/oyiVZvPu63gc9gDqGTnhKisHV2IFdiQAIUyS4yFpT/l6Z/i3EmRU2Mfp+Po21A==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@deephaven/react-hooks/-/react-hooks-1.14.0.tgz", + "integrity": "sha512-VWRU6Hka5GyN0zO5LJYI5YgKrEsf0xAKrQ5LnEX4WSloB1C5DFoS1K1kH3fPqVBhid5JTu7R7oe0y4Tvt4wesQ==", + "license": "Apache-2.0", "dependencies": { "@adobe/react-spectrum": "3.38.0", - "@deephaven/log": "^1.1.0", - "@deephaven/utils": "^1.1.0", + "@deephaven/log": "^1.8.0", + "@deephaven/utils": "^1.10.0", "lodash.debounce": "^4.0.8", "lodash.throttle": "^4.1.1", "nanoid": "^5.0.7" @@ -35578,15 +35514,16 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/redux": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@deephaven/redux/-/redux-1.5.1.tgz", - "integrity": "sha512-jTSD9rFVl14bUyOGuS7PZnXIcaYem80EoQjvNkfUcQZ8EYjOKt90iDvGve0dtNou6nsLRqggS7HeADBLh8jffw==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@deephaven/redux/-/redux-1.17.0.tgz", + "integrity": "sha512-pbq1Npd0JHkZDiK7gt5Oj4EVJuikQ76Jd0qoo20P5Ouan5M2iZg3HZNHVmicAJHA9p7+EmYAeXpHS52rUmQszg==", + "license": "Apache-2.0", "dependencies": { - "@deephaven/jsapi-types": "^1.0.0-dev0.39.4", - "@deephaven/jsapi-utils": "^1.4.0", - "@deephaven/log": "^1.1.0", - "@deephaven/plugin": "^1.5.1", + "@deephaven/jsapi-types": "^1.0.0-dev0.40.4", + "@deephaven/jsapi-utils": "^1.16.0", + "@deephaven/log": "^1.8.0", "fast-deep-equal": "^3.1.3", + "lodash.mergewith": "^4.6.2", "proxy-memoize": "^3.0.0", "redux-thunk": "2.4.1" }, @@ -35597,26 +35534,118 @@ "redux": "^4.2.0" } }, + "plugins/ui/src/js/node_modules/@deephaven/storage": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@deephaven/storage/-/storage-1.8.0.tgz", + "integrity": "sha512-uQm87RZofAsmhLzt4wayME5b6d7/H86PR5NTjdj4z9dV2KBVUpSryTUAkx84t3G6XVsOH4A5Xb7PtmXWh5Mz4g==", + "license": "Apache-2.0", + "dependencies": { + "@deephaven/filters": "^1.1.0", + "@deephaven/log": "^1.8.0", + "lodash.throttle": "^4.1.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "plugins/ui/src/js/node_modules/@deephaven/utils": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@deephaven/utils/-/utils-1.1.0.tgz", - "integrity": "sha512-GIEwXa5fdq2RWF2kx9YSu12mqhpt15YY4Z3pbdfZFMbLw/ilPZKVhpJK/twlFFo69ruwcetwORrVS2SKW4ng2g==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@deephaven/utils/-/utils-1.10.0.tgz", + "integrity": "sha512-KLs73wIU/T3ZA+H+YTlzQ1fT+6p02RfixMQ7+l8S+IyLxc+nwSMABYnoZybJJuRvw1huJuFv1+n0B0HDteDFZA==", + "license": "Apache-2.0", "dependencies": { - "@deephaven/log": "^1.1.0", + "@deephaven/log": "^1.8.0", "nanoid": "^5.0.7" }, "engines": { "node": ">=16" } }, + "plugins/ui/src/js/node_modules/@dnd-kit/sortable": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz", + "integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==", + "license": "MIT", + "dependencies": { + "@dnd-kit/utilities": "^3.2.2", + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@dnd-kit/core": "^6.3.0", + "react": ">=16.8.0" + } + }, + "plugins/ui/src/js/node_modules/@hello-pangea/dnd": { + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/@hello-pangea/dnd/-/dnd-18.0.1.tgz", + "integrity": "sha512-xojVWG8s/TGrKT1fC8K2tIWeejJYTAeJuj36zM//yEm/ZrnZUSFGS15BpO+jGZT1ybWvyXmeDJwPYb4dhWlbZQ==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.26.7", + "css-box-model": "^1.2.1", + "raf-schd": "^4.0.3", + "react-redux": "^9.2.0", + "redux": "^5.0.1" + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + } + }, + "plugins/ui/src/js/node_modules/@hello-pangea/dnd/node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "plugins/ui/src/js/node_modules/@hello-pangea/dnd/node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT", + "peer": true + }, "plugins/ui/src/js/node_modules/@types/mathjax": { "version": "0.0.37", "license": "MIT" }, + "plugins/ui/src/js/node_modules/@types/react": { + "version": "18.3.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", + "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, "plugins/ui/src/js/node_modules/color-rgba": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/color-rgba/-/color-rgba-3.0.0.tgz", "integrity": "sha512-PPwZYkEY3M2THEHHV6Y95sGUie77S7X8v+h1r6LSAPF3/LL2xJ8duUXSrkic31Nzc4odPwHgUbiX/XuTYzQHQg==", + "license": "MIT", "dependencies": { "color-parse": "^2.0.0", "color-space": "^2.0.0" @@ -35625,7 +35654,8 @@ "plugins/ui/src/js/node_modules/color-space": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/color-space/-/color-space-2.3.2.tgz", - "integrity": "sha512-BcKnbOEsOarCwyoLstcoEztwT0IJxqqQkNwDuA3a65sICvvHL2yoeV13psoDFh5IuiOMnIOKdQDwB4Mk3BypiA==" + "integrity": "sha512-BcKnbOEsOarCwyoLstcoEztwT0IJxqqQkNwDuA3a65sICvvHL2yoeV13psoDFh5IuiOMnIOKdQDwB4Mk3BypiA==", + "license": "Unlicense" }, "plugins/ui/src/js/node_modules/hast-util-from-dom": { "version": "4.2.0", @@ -35692,9 +35722,10 @@ } }, "plugins/ui/src/js/node_modules/plotly.js": { - "version": "3.1.0-rc.0", - "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-3.1.0-rc.0.tgz", - "integrity": "sha512-7yOQs7cHBpc/aA8MV39EjPNLPYb5F4+w0kMgUWgIlDQ7TzWUtfuD8rM70KjzLgsZmBcP7O8sZ27ugezbllcftg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-3.1.0.tgz", + "integrity": "sha512-vx+CyzApL9tquFpwoPHOGSIWDbFPsA4om/tXZcnsygGUejXideDF9R5VwkltEIDG7Xuof45quVPyz1otv6Aqjw==", + "license": "MIT", "dependencies": { "@plotly/d3": "3.8.2", "@plotly/d3-sankey": "0.7.2", @@ -35751,14 +35782,64 @@ "node": ">=18.0.0" } }, + "plugins/ui/src/js/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "plugins/ui/src/js/node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "plugins/ui/src/js/node_modules/react-virtualized-auto-sizer": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.7.tgz", + "integrity": "sha512-Mxi6lwOmjwIjC1X4gABXMJcKHsOo0xWl3E3ugOgufB8GJU+MqrtY35aBuvCYv/razQ1Vbp7h1gWJjGjoNN5pmA==", + "license": "MIT", + "engines": { + "node": ">8.0.0" + }, + "peerDependencies": { + "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc", + "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc" + } + }, "plugins/ui/src/js/node_modules/redux-thunk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", + "license": "MIT", "peerDependencies": { "redux": "^4" } }, + "plugins/ui/src/js/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "plugins/ui/src/js/node_modules/unist-util-find-after": { "version": "4.0.1", "license": "MIT", From d6cfcabe13dce1ada54d96a70e16dfa30274f4a3 Mon Sep 17 00:00:00 2001 From: mikebender Date: Mon, 13 Apr 2026 11:09:51 -0400 Subject: [PATCH 07/15] chore: update all plugins to React 18 types with v17/v18/v19 peer deps --- package-lock.json | 309 ++++++++++++++---- package.json | 4 +- plugins/ag-grid/src/js/package.json | 6 +- plugins/auth-keycloak/src/js/package.json | 6 +- .../src/js/package.json | 8 +- plugins/matplotlib/src/js/package.json | 12 +- plugins/pivot/src/js/package.json | 10 +- plugins/plotly-express/src/js/package.json | 10 +- .../src/js/package.json | 10 +- plugins/simple-pivot/src/js/package.json | 10 +- plugins/table-example/src/js/package.json | 6 +- plugins/ui/src/js/package.json | 4 +- 12 files changed, 285 insertions(+), 110 deletions(-) diff --git a/package-lock.json b/package-lock.json index 54ac048d2..49b4e1150 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12033,6 +12033,16 @@ "node": ">=12" } }, + "node_modules/@testing-library/react/node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, "node_modules/@testing-library/react/node_modules/aria-query": { "version": "5.1.3", "dev": true, @@ -12489,21 +12499,14 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "17.0.83", + "version": "18.3.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", + "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", "license": "MIT", "peer": true, "dependencies": { "@types/prop-types": "*", - "@types/scheduler": "^0.16", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "17.0.26", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^17.0.0" + "csstype": "^3.2.2" } }, "node_modules/@types/react-plotly.js": { @@ -12525,10 +12528,6 @@ "redux": "^4.0.0" } }, - "node_modules/@types/scheduler": { - "version": "0.16.8", - "license": "MIT" - }, "node_modules/@types/semver": { "version": "7.5.8", "dev": true, @@ -30785,9 +30784,9 @@ "devDependencies": { "@deephaven/jsapi-types": "^1.0.0-dev0.39.1", "@deephaven/test-utils": "^0.106.0", - "@types/react": "^17.0.2", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "@types/react": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "peerDependencies": { "react": "^17.0.2 || ^18.0.0 || ^19.0.0", @@ -30957,6 +30956,33 @@ "node": ">=16" } }, + "plugins/ag-grid/src/js/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "plugins/ag-grid/src/js/node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, "plugins/ag-grid/src/js/node_modules/redux-thunk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", @@ -30966,6 +30992,15 @@ "redux": "^4" } }, + "plugins/ag-grid/src/js/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "plugins/auth-keycloak/src/js": { "name": "@deephaven/js-plugin-auth-keycloak", "version": "0.2.0", @@ -30981,11 +31016,24 @@ "keycloak-js": "^21.0.2" }, "devDependencies": { - "@types/react": "^17.0.2", - "react": "^17.0.2" + "@types/react": "^18.0.0", + "react": "^18.0.0" }, "peerDependencies": { - "react": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0" + } + }, + "plugins/auth-keycloak/src/js/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, "plugins/dashboard-object-viewer/src/js": { @@ -31001,13 +31049,26 @@ "react-json-view": "^1.21.3" }, "devDependencies": { - "@types/react": "^17.0.2", - "react": "^17.0.2", + "@types/react": "^18.0.0", + "react": "^18.0.0", "sass": "^1.60.0" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + } + }, + "plugins/dashboard-object-viewer/src/js/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, "plugins/deephaven_plugin_template/src/js": { @@ -31061,14 +31122,14 @@ "nanoid": "^5.0.7" }, "devDependencies": { - "@types/react": "^17.0.2", - "@types/react-dom": "^17.0.2", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" } }, "plugins/matplotlib/src/js/node_modules/@deephaven/components": { @@ -31653,6 +31714,33 @@ "node": ">=16" } }, + "plugins/matplotlib/src/js/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "plugins/matplotlib/src/js/node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, "plugins/matplotlib/src/js/node_modules/redux-thunk": { "version": "2.4.1", "license": "MIT", @@ -31660,6 +31748,15 @@ "redux": "^4" } }, + "plugins/matplotlib/src/js/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "plugins/pivot/src/js": { "name": "@deephaven/js-plugin-pivot", "version": "0.4.0", @@ -31687,15 +31784,15 @@ "@deephaven/tsconfig": "^0.72.0", "@types/lodash.clamp": "^4.0.9", "@types/lodash.throttle": "^4.1.9", - "@types/react": "^17.0.2", - "@types/react-dom": "^17.0.2", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", "@vitejs/plugin-react-swc": "^3.0.0", - "react": "^17.0.2", + "react": "^18.0.0", "vite": "~4.1.4" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" } }, "plugins/pivot/src/js/node_modules/@deephaven/components": { @@ -32184,6 +32281,19 @@ "integrity": "sha512-1o4olnZJsiLmv5pwLEAmzHTE/5geLKQ07BrGxlF4Ri/AXAc2yyDGZwHjiTqD8D/ROKUZmwMA28A+yEowLNOEcA==", "license": "MIT" }, + "plugins/pivot/src/js/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "plugins/pivot/src/js/node_modules/rollup": { "version": "3.29.5", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", @@ -32279,15 +32389,15 @@ "@types/deep-equal": "^1.0.1", "@types/plotly.js": "^3.0.0", "@types/plotly.js-dist-min": "^2.3.1", - "@types/react": "^17.0.2", + "@types/react": "^18.0.0", "@types/react-plotly.js": "^2.6.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.0.0", + "react-dom": "^18.0.0", "typescript": "^5.9.3" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" } }, "plugins/plotly-express/src/js/node_modules/@deephaven/chart": { @@ -33424,6 +33534,42 @@ "node": ">=18.0.0" } }, + "plugins/plotly-express/src/js/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "plugins/plotly-express/src/js/node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "plugins/plotly-express/src/js/node_modules/react-dom/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "plugins/plotly-express/src/js/node_modules/redux-thunk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", @@ -33497,16 +33643,16 @@ }, "devDependencies": { "@deephaven/tsconfig": "^0.72.0", - "@types/react": "^17.0.2", - "@types/react-dom": "^17.0.2", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", "@vitejs/plugin-react-swc": "^3.0.0", - "react": "^17.0.2", + "react": "^18.0.0", "typescript": "^5.9.3", "vite": "^5.4.6" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" } }, "plugins/python-remote-file-source/src/js/node_modules/@deephaven/components": { @@ -33939,6 +34085,19 @@ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.41.0.tgz", "integrity": "sha512-1o4olnZJsiLmv5pwLEAmzHTE/5geLKQ07BrGxlF4Ri/AXAc2yyDGZwHjiTqD8D/ROKUZmwMA28A+yEowLNOEcA==" }, + "plugins/python-remote-file-source/src/js/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "plugins/simple-pivot/src/js": { "name": "@deephaven/js-plugin-simple-pivot", "version": "0.0.3-dev.2", @@ -33960,15 +34119,15 @@ "devDependencies": { "@deephaven/jsapi-types": "^1.0.0-dev0.35.2", "@deephaven/tsconfig": "^0.72.0", - "@types/react": "^17.0.2", - "@types/react-dom": "^17.0.2", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", "@vitejs/plugin-react-swc": "^3.0.0", - "react": "^17.0.2", + "react": "^18.0.0", "vite": "~4.1.4" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" } }, "plugins/simple-pivot/src/js/node_modules/@deephaven/components": { @@ -34441,6 +34600,19 @@ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.41.0.tgz", "integrity": "sha512-1o4olnZJsiLmv5pwLEAmzHTE/5geLKQ07BrGxlF4Ri/AXAc2yyDGZwHjiTqD8D/ROKUZmwMA28A+yEowLNOEcA==" }, + "plugins/simple-pivot/src/js/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "plugins/simple-pivot/src/js/node_modules/rollup": { "version": "3.29.5", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", @@ -34515,11 +34687,24 @@ "@deephaven/jsapi-types": "^0.40.0" }, "devDependencies": { - "@types/react": "^17.0.2", - "react": "^17.0.2" + "@types/react": "^18.0.0", + "react": "^18.0.0" }, "peerDependencies": { - "react": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0" + } + }, + "plugins/table-example/src/js/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, "plugins/theme-pack/src/js": { @@ -35035,8 +35220,8 @@ "react-dom": "^18.0.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" } }, "plugins/ui/src/js/node_modules/@deephaven/chart": { @@ -35629,18 +35814,6 @@ "version": "0.0.37", "license": "MIT" }, - "plugins/ui/src/js/node_modules/@types/react": { - "version": "18.3.28", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", - "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", - "devOptional": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.2.2" - } - }, "plugins/ui/src/js/node_modules/color-rgba": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/color-rgba/-/color-rgba-3.0.0.tgz", diff --git a/package.json b/package.json index d24145cf2..a3c4da34b 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,9 @@ "overrides": { "@deephaven/eslint-config": { "eslint-import-resolver-typescript": "3.5.0" - } + }, + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0" }, "prettier": "@deephaven/prettier-config" } diff --git a/plugins/ag-grid/src/js/package.json b/plugins/ag-grid/src/js/package.json index be757dd86..8987db1d0 100644 --- a/plugins/ag-grid/src/js/package.json +++ b/plugins/ag-grid/src/js/package.json @@ -39,9 +39,9 @@ "devDependencies": { "@deephaven/jsapi-types": "^1.0.0-dev0.39.1", "@deephaven/test-utils": "^0.106.0", - "@types/react": "^17.0.2", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "@types/react": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "peerDependencies": { "react": "^17.0.2 || ^18.0.0 || ^19.0.0", diff --git a/plugins/auth-keycloak/src/js/package.json b/plugins/auth-keycloak/src/js/package.json index 3b05447a5..b838df05a 100644 --- a/plugins/auth-keycloak/src/js/package.json +++ b/plugins/auth-keycloak/src/js/package.json @@ -27,11 +27,11 @@ "update-dh-packages": "node ../../../../tools/update-dh-packages.mjs" }, "devDependencies": { - "@types/react": "^17.0.2", - "react": "^17.0.2" + "@types/react": "^18.0.0", + "react": "^18.0.0" }, "peerDependencies": { - "react": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0" }, "dependencies": { "@deephaven/auth-plugins": "^0.40.0", diff --git a/plugins/dashboard-object-viewer/src/js/package.json b/plugins/dashboard-object-viewer/src/js/package.json index 922f60469..f09922709 100644 --- a/plugins/dashboard-object-viewer/src/js/package.json +++ b/plugins/dashboard-object-viewer/src/js/package.json @@ -27,13 +27,13 @@ "react-json-view": "^1.21.3" }, "devDependencies": { - "@types/react": "^17.0.2", - "react": "^17.0.2", + "@types/react": "^18.0.0", + "react": "^18.0.0", "sass": "^1.60.0" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" }, "publishConfig": { "access": "public" diff --git a/plugins/matplotlib/src/js/package.json b/plugins/matplotlib/src/js/package.json index f8ae06dd5..42d648c7a 100644 --- a/plugins/matplotlib/src/js/package.json +++ b/plugins/matplotlib/src/js/package.json @@ -26,14 +26,14 @@ "update-dh-packages": "node ../../../../tools/update-dh-packages.mjs" }, "devDependencies": { - "@types/react": "^17.0.2", - "@types/react-dom": "^17.0.2", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" }, "dependencies": { "@deephaven/components": "^0.87.0", diff --git a/plugins/pivot/src/js/package.json b/plugins/pivot/src/js/package.json index 6ef0597be..876f70f45 100644 --- a/plugins/pivot/src/js/package.json +++ b/plugins/pivot/src/js/package.json @@ -25,15 +25,15 @@ "@deephaven/tsconfig": "^0.72.0", "@types/lodash.clamp": "^4.0.9", "@types/lodash.throttle": "^4.1.9", - "@types/react": "^17.0.2", - "@types/react-dom": "^17.0.2", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", "@vitejs/plugin-react-swc": "^3.0.0", - "react": "^17.0.2", + "react": "^18.0.0", "vite": "~4.1.4" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" }, "dependencies": { "@deephaven/components": "^0.85.35", diff --git a/plugins/plotly-express/src/js/package.json b/plugins/plotly-express/src/js/package.json index 156c8a14b..767823862 100644 --- a/plugins/plotly-express/src/js/package.json +++ b/plugins/plotly-express/src/js/package.json @@ -43,15 +43,15 @@ "@types/deep-equal": "^1.0.1", "@types/plotly.js": "^3.0.0", "@types/plotly.js-dist-min": "^2.3.1", - "@types/react": "^17.0.2", + "@types/react": "^18.0.0", "@types/react-plotly.js": "^2.6.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.0.0", + "react-dom": "^18.0.0", "typescript": "^5.9.3" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" }, "dependencies": { "@deephaven/chart": "^1.17.0", diff --git a/plugins/python-remote-file-source/src/js/package.json b/plugins/python-remote-file-source/src/js/package.json index b560250ca..5d409e3b4 100644 --- a/plugins/python-remote-file-source/src/js/package.json +++ b/plugins/python-remote-file-source/src/js/package.json @@ -19,16 +19,16 @@ }, "devDependencies": { "@deephaven/tsconfig": "^0.72.0", - "@types/react": "^17.0.2", + "@types/react": "^18.0.0", "@vitejs/plugin-react-swc": "^3.0.0", - "@types/react-dom": "^17.0.2", - "react": "^17.0.2", + "@types/react-dom": "^18.0.0", + "react": "^18.0.0", "typescript": "^5.9.3", "vite": "^5.4.6" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" }, "dependencies": { "@deephaven/components": "^0.85.0", diff --git a/plugins/simple-pivot/src/js/package.json b/plugins/simple-pivot/src/js/package.json index a901e8ab5..cebaff004 100644 --- a/plugins/simple-pivot/src/js/package.json +++ b/plugins/simple-pivot/src/js/package.json @@ -20,15 +20,15 @@ "devDependencies": { "@deephaven/jsapi-types": "^1.0.0-dev0.35.2", "@deephaven/tsconfig": "^0.72.0", - "@types/react": "^17.0.2", - "@types/react-dom": "^17.0.2", + "@types/react": "^18.0.0", + "@types/react-dom": "^18.0.0", "@vitejs/plugin-react-swc": "^3.0.0", - "react": "^17.0.2", + "react": "^18.0.0", "vite": "~4.1.4" }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" }, "dependencies": { "@deephaven/components": "^0.85.27", diff --git a/plugins/table-example/src/js/package.json b/plugins/table-example/src/js/package.json index e4ade9036..9888d6f6c 100644 --- a/plugins/table-example/src/js/package.json +++ b/plugins/table-example/src/js/package.json @@ -22,11 +22,11 @@ "@deephaven/jsapi-types": "^0.40.0" }, "devDependencies": { - "@types/react": "^17.0.2", - "react": "^17.0.2" + "@types/react": "^18.0.0", + "react": "^18.0.0" }, "peerDependencies": { - "react": "^17.0.2" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0" }, "publishConfig": { "access": "public" diff --git a/plugins/ui/src/js/package.json b/plugins/ui/src/js/package.json index 087106179..f209e49c4 100644 --- a/plugins/ui/src/js/package.json +++ b/plugins/ui/src/js/package.json @@ -36,8 +36,8 @@ "react-dom": "^18.0.0" }, "peerDependencies": { - "react": "^18.0.0", - "react-dom": "^18.0.0" + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" }, "dependencies": { "@deephaven/components": "^1.17.0", From 74b7f3c78e86a64599238b5f4b2bf661e48878f5 Mon Sep 17 00:00:00 2001 From: mikebender Date: Mon, 13 Apr 2026 13:17:36 -0400 Subject: [PATCH 08/15] Update package-lock.json --- package-lock.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 49b4e1150..22b917592 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12033,16 +12033,6 @@ "node": ">=12" } }, - "node_modules/@testing-library/react/node_modules/@types/react-dom": { - "version": "18.3.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", - "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^18.0.0" - } - }, "node_modules/@testing-library/react/node_modules/aria-query": { "version": "5.1.3", "dev": true, @@ -12509,6 +12499,16 @@ "csstype": "^3.2.2" } }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, "node_modules/@types/react-plotly.js": { "version": "2.6.3", "dev": true, From f02c81054e1cb091fbd6f5189393b80c1006e5c8 Mon Sep 17 00:00:00 2001 From: mikebender Date: Mon, 13 Apr 2026 13:48:29 -0400 Subject: [PATCH 09/15] Revert "Update package-lock.json" This reverts commit 74b7f3c78e86a64599238b5f4b2bf661e48878f5. --- package-lock.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 22b917592..49b4e1150 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12033,6 +12033,16 @@ "node": ">=12" } }, + "node_modules/@testing-library/react/node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, "node_modules/@testing-library/react/node_modules/aria-query": { "version": "5.1.3", "dev": true, @@ -12499,16 +12509,6 @@ "csstype": "^3.2.2" } }, - "node_modules/@types/react-dom": { - "version": "18.3.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", - "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^18.0.0" - } - }, "node_modules/@types/react-plotly.js": { "version": "2.6.3", "dev": true, From 36151920d9a502c42420f407c443e54213ba1a7e Mon Sep 17 00:00:00 2001 From: mikebender Date: Mon, 13 Apr 2026 13:48:34 -0400 Subject: [PATCH 10/15] Revert "chore: update all plugins to React 18 types with v17/v18/v19 peer deps" This reverts commit d6cfcabe13dce1ada54d96a70e16dfa30274f4a3. --- package-lock.json | 309 ++++-------------- package.json | 4 +- plugins/ag-grid/src/js/package.json | 6 +- plugins/auth-keycloak/src/js/package.json | 6 +- .../src/js/package.json | 8 +- plugins/matplotlib/src/js/package.json | 12 +- plugins/pivot/src/js/package.json | 10 +- plugins/plotly-express/src/js/package.json | 10 +- .../src/js/package.json | 10 +- plugins/simple-pivot/src/js/package.json | 10 +- plugins/table-example/src/js/package.json | 6 +- plugins/ui/src/js/package.json | 4 +- 12 files changed, 110 insertions(+), 285 deletions(-) diff --git a/package-lock.json b/package-lock.json index 49b4e1150..54ac048d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12033,16 +12033,6 @@ "node": ">=12" } }, - "node_modules/@testing-library/react/node_modules/@types/react-dom": { - "version": "18.3.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", - "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^18.0.0" - } - }, "node_modules/@testing-library/react/node_modules/aria-query": { "version": "5.1.3", "dev": true, @@ -12499,14 +12489,21 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.3.28", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", - "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", + "version": "17.0.83", "license": "MIT", "peer": true, "dependencies": { "@types/prop-types": "*", - "csstype": "^3.2.2" + "@types/scheduler": "^0.16", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "17.0.26", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^17.0.0" } }, "node_modules/@types/react-plotly.js": { @@ -12528,6 +12525,10 @@ "redux": "^4.0.0" } }, + "node_modules/@types/scheduler": { + "version": "0.16.8", + "license": "MIT" + }, "node_modules/@types/semver": { "version": "7.5.8", "dev": true, @@ -30784,9 +30785,9 @@ "devDependencies": { "@deephaven/jsapi-types": "^1.0.0-dev0.39.1", "@deephaven/test-utils": "^0.106.0", - "@types/react": "^18.0.0", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@types/react": "^17.0.2", + "react": "^17.0.2", + "react-dom": "^17.0.2" }, "peerDependencies": { "react": "^17.0.2 || ^18.0.0 || ^19.0.0", @@ -30956,33 +30957,6 @@ "node": ">=16" } }, - "plugins/ag-grid/src/js/node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "plugins/ag-grid/src/js/node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, "plugins/ag-grid/src/js/node_modules/redux-thunk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", @@ -30992,15 +30966,6 @@ "redux": "^4" } }, - "plugins/ag-grid/src/js/node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, "plugins/auth-keycloak/src/js": { "name": "@deephaven/js-plugin-auth-keycloak", "version": "0.2.0", @@ -31016,24 +30981,11 @@ "keycloak-js": "^21.0.2" }, "devDependencies": { - "@types/react": "^18.0.0", - "react": "^18.0.0" + "@types/react": "^17.0.2", + "react": "^17.0.2" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0" - } - }, - "plugins/auth-keycloak/src/js/node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" + "react": "^17.0.2" } }, "plugins/dashboard-object-viewer/src/js": { @@ -31049,26 +31001,13 @@ "react-json-view": "^1.21.3" }, "devDependencies": { - "@types/react": "^18.0.0", - "react": "^18.0.0", + "@types/react": "^17.0.2", + "react": "^17.0.2", "sass": "^1.60.0" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" - } - }, - "plugins/dashboard-object-viewer/src/js/node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" + "react": "^17.0.2", + "react-dom": "^17.0.2" } }, "plugins/deephaven_plugin_template/src/js": { @@ -31122,14 +31061,14 @@ "nanoid": "^5.0.7" }, "devDependencies": { - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@types/react": "^17.0.2", + "@types/react-dom": "^17.0.2", + "react": "^17.0.2", + "react-dom": "^17.0.2" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2", + "react-dom": "^17.0.2" } }, "plugins/matplotlib/src/js/node_modules/@deephaven/components": { @@ -31714,33 +31653,6 @@ "node": ">=16" } }, - "plugins/matplotlib/src/js/node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "plugins/matplotlib/src/js/node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, "plugins/matplotlib/src/js/node_modules/redux-thunk": { "version": "2.4.1", "license": "MIT", @@ -31748,15 +31660,6 @@ "redux": "^4" } }, - "plugins/matplotlib/src/js/node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, "plugins/pivot/src/js": { "name": "@deephaven/js-plugin-pivot", "version": "0.4.0", @@ -31784,15 +31687,15 @@ "@deephaven/tsconfig": "^0.72.0", "@types/lodash.clamp": "^4.0.9", "@types/lodash.throttle": "^4.1.9", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", + "@types/react": "^17.0.2", + "@types/react-dom": "^17.0.2", "@vitejs/plugin-react-swc": "^3.0.0", - "react": "^18.0.0", + "react": "^17.0.2", "vite": "~4.1.4" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2", + "react-dom": "^17.0.2" } }, "plugins/pivot/src/js/node_modules/@deephaven/components": { @@ -32281,19 +32184,6 @@ "integrity": "sha512-1o4olnZJsiLmv5pwLEAmzHTE/5geLKQ07BrGxlF4Ri/AXAc2yyDGZwHjiTqD8D/ROKUZmwMA28A+yEowLNOEcA==", "license": "MIT" }, - "plugins/pivot/src/js/node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "plugins/pivot/src/js/node_modules/rollup": { "version": "3.29.5", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", @@ -32389,15 +32279,15 @@ "@types/deep-equal": "^1.0.1", "@types/plotly.js": "^3.0.0", "@types/plotly.js-dist-min": "^2.3.1", - "@types/react": "^18.0.0", + "@types/react": "^17.0.2", "@types/react-plotly.js": "^2.6.0", - "react": "^18.0.0", - "react-dom": "^18.0.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", "typescript": "^5.9.3" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2", + "react-dom": "^17.0.2" } }, "plugins/plotly-express/src/js/node_modules/@deephaven/chart": { @@ -33534,42 +33424,6 @@ "node": ">=18.0.0" } }, - "plugins/plotly-express/src/js/node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "plugins/plotly-express/src/js/node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "plugins/plotly-express/src/js/node_modules/react-dom/node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, "plugins/plotly-express/src/js/node_modules/redux-thunk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", @@ -33643,16 +33497,16 @@ }, "devDependencies": { "@deephaven/tsconfig": "^0.72.0", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", + "@types/react": "^17.0.2", + "@types/react-dom": "^17.0.2", "@vitejs/plugin-react-swc": "^3.0.0", - "react": "^18.0.0", + "react": "^17.0.2", "typescript": "^5.9.3", "vite": "^5.4.6" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2", + "react-dom": "^17.0.2" } }, "plugins/python-remote-file-source/src/js/node_modules/@deephaven/components": { @@ -34085,19 +33939,6 @@ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.41.0.tgz", "integrity": "sha512-1o4olnZJsiLmv5pwLEAmzHTE/5geLKQ07BrGxlF4Ri/AXAc2yyDGZwHjiTqD8D/ROKUZmwMA28A+yEowLNOEcA==" }, - "plugins/python-remote-file-source/src/js/node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "plugins/simple-pivot/src/js": { "name": "@deephaven/js-plugin-simple-pivot", "version": "0.0.3-dev.2", @@ -34119,15 +33960,15 @@ "devDependencies": { "@deephaven/jsapi-types": "^1.0.0-dev0.35.2", "@deephaven/tsconfig": "^0.72.0", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", + "@types/react": "^17.0.2", + "@types/react-dom": "^17.0.2", "@vitejs/plugin-react-swc": "^3.0.0", - "react": "^18.0.0", + "react": "^17.0.2", "vite": "~4.1.4" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2", + "react-dom": "^17.0.2" } }, "plugins/simple-pivot/src/js/node_modules/@deephaven/components": { @@ -34600,19 +34441,6 @@ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.41.0.tgz", "integrity": "sha512-1o4olnZJsiLmv5pwLEAmzHTE/5geLKQ07BrGxlF4Ri/AXAc2yyDGZwHjiTqD8D/ROKUZmwMA28A+yEowLNOEcA==" }, - "plugins/simple-pivot/src/js/node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "plugins/simple-pivot/src/js/node_modules/rollup": { "version": "3.29.5", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", @@ -34687,24 +34515,11 @@ "@deephaven/jsapi-types": "^0.40.0" }, "devDependencies": { - "@types/react": "^18.0.0", - "react": "^18.0.0" + "@types/react": "^17.0.2", + "react": "^17.0.2" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0" - } - }, - "plugins/table-example/src/js/node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" + "react": "^17.0.2" } }, "plugins/theme-pack/src/js": { @@ -35220,8 +35035,8 @@ "react-dom": "^18.0.0" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^18.0.0", + "react-dom": "^18.0.0" } }, "plugins/ui/src/js/node_modules/@deephaven/chart": { @@ -35814,6 +35629,18 @@ "version": "0.0.37", "license": "MIT" }, + "plugins/ui/src/js/node_modules/@types/react": { + "version": "18.3.28", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", + "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, "plugins/ui/src/js/node_modules/color-rgba": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/color-rgba/-/color-rgba-3.0.0.tgz", diff --git a/package.json b/package.json index a3c4da34b..d24145cf2 100644 --- a/package.json +++ b/package.json @@ -111,9 +111,7 @@ "overrides": { "@deephaven/eslint-config": { "eslint-import-resolver-typescript": "3.5.0" - }, - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0" + } }, "prettier": "@deephaven/prettier-config" } diff --git a/plugins/ag-grid/src/js/package.json b/plugins/ag-grid/src/js/package.json index 8987db1d0..be757dd86 100644 --- a/plugins/ag-grid/src/js/package.json +++ b/plugins/ag-grid/src/js/package.json @@ -39,9 +39,9 @@ "devDependencies": { "@deephaven/jsapi-types": "^1.0.0-dev0.39.1", "@deephaven/test-utils": "^0.106.0", - "@types/react": "^18.0.0", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@types/react": "^17.0.2", + "react": "^17.0.2", + "react-dom": "^17.0.2" }, "peerDependencies": { "react": "^17.0.2 || ^18.0.0 || ^19.0.0", diff --git a/plugins/auth-keycloak/src/js/package.json b/plugins/auth-keycloak/src/js/package.json index b838df05a..3b05447a5 100644 --- a/plugins/auth-keycloak/src/js/package.json +++ b/plugins/auth-keycloak/src/js/package.json @@ -27,11 +27,11 @@ "update-dh-packages": "node ../../../../tools/update-dh-packages.mjs" }, "devDependencies": { - "@types/react": "^18.0.0", - "react": "^18.0.0" + "@types/react": "^17.0.2", + "react": "^17.0.2" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2" }, "dependencies": { "@deephaven/auth-plugins": "^0.40.0", diff --git a/plugins/dashboard-object-viewer/src/js/package.json b/plugins/dashboard-object-viewer/src/js/package.json index f09922709..922f60469 100644 --- a/plugins/dashboard-object-viewer/src/js/package.json +++ b/plugins/dashboard-object-viewer/src/js/package.json @@ -27,13 +27,13 @@ "react-json-view": "^1.21.3" }, "devDependencies": { - "@types/react": "^18.0.0", - "react": "^18.0.0", + "@types/react": "^17.0.2", + "react": "^17.0.2", "sass": "^1.60.0" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2", + "react-dom": "^17.0.2" }, "publishConfig": { "access": "public" diff --git a/plugins/matplotlib/src/js/package.json b/plugins/matplotlib/src/js/package.json index 42d648c7a..f8ae06dd5 100644 --- a/plugins/matplotlib/src/js/package.json +++ b/plugins/matplotlib/src/js/package.json @@ -26,14 +26,14 @@ "update-dh-packages": "node ../../../../tools/update-dh-packages.mjs" }, "devDependencies": { - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", - "react": "^18.0.0", - "react-dom": "^18.0.0" + "@types/react": "^17.0.2", + "@types/react-dom": "^17.0.2", + "react": "^17.0.2", + "react-dom": "^17.0.2" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2", + "react-dom": "^17.0.2" }, "dependencies": { "@deephaven/components": "^0.87.0", diff --git a/plugins/pivot/src/js/package.json b/plugins/pivot/src/js/package.json index 876f70f45..6ef0597be 100644 --- a/plugins/pivot/src/js/package.json +++ b/plugins/pivot/src/js/package.json @@ -25,15 +25,15 @@ "@deephaven/tsconfig": "^0.72.0", "@types/lodash.clamp": "^4.0.9", "@types/lodash.throttle": "^4.1.9", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", + "@types/react": "^17.0.2", + "@types/react-dom": "^17.0.2", "@vitejs/plugin-react-swc": "^3.0.0", - "react": "^18.0.0", + "react": "^17.0.2", "vite": "~4.1.4" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2", + "react-dom": "^17.0.2" }, "dependencies": { "@deephaven/components": "^0.85.35", diff --git a/plugins/plotly-express/src/js/package.json b/plugins/plotly-express/src/js/package.json index 767823862..156c8a14b 100644 --- a/plugins/plotly-express/src/js/package.json +++ b/plugins/plotly-express/src/js/package.json @@ -43,15 +43,15 @@ "@types/deep-equal": "^1.0.1", "@types/plotly.js": "^3.0.0", "@types/plotly.js-dist-min": "^2.3.1", - "@types/react": "^18.0.0", + "@types/react": "^17.0.2", "@types/react-plotly.js": "^2.6.0", - "react": "^18.0.0", - "react-dom": "^18.0.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", "typescript": "^5.9.3" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2", + "react-dom": "^17.0.2" }, "dependencies": { "@deephaven/chart": "^1.17.0", diff --git a/plugins/python-remote-file-source/src/js/package.json b/plugins/python-remote-file-source/src/js/package.json index 5d409e3b4..b560250ca 100644 --- a/plugins/python-remote-file-source/src/js/package.json +++ b/plugins/python-remote-file-source/src/js/package.json @@ -19,16 +19,16 @@ }, "devDependencies": { "@deephaven/tsconfig": "^0.72.0", - "@types/react": "^18.0.0", + "@types/react": "^17.0.2", "@vitejs/plugin-react-swc": "^3.0.0", - "@types/react-dom": "^18.0.0", - "react": "^18.0.0", + "@types/react-dom": "^17.0.2", + "react": "^17.0.2", "typescript": "^5.9.3", "vite": "^5.4.6" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2", + "react-dom": "^17.0.2" }, "dependencies": { "@deephaven/components": "^0.85.0", diff --git a/plugins/simple-pivot/src/js/package.json b/plugins/simple-pivot/src/js/package.json index cebaff004..a901e8ab5 100644 --- a/plugins/simple-pivot/src/js/package.json +++ b/plugins/simple-pivot/src/js/package.json @@ -20,15 +20,15 @@ "devDependencies": { "@deephaven/jsapi-types": "^1.0.0-dev0.35.2", "@deephaven/tsconfig": "^0.72.0", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", + "@types/react": "^17.0.2", + "@types/react-dom": "^17.0.2", "@vitejs/plugin-react-swc": "^3.0.0", - "react": "^18.0.0", + "react": "^17.0.2", "vite": "~4.1.4" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2", + "react-dom": "^17.0.2" }, "dependencies": { "@deephaven/components": "^0.85.27", diff --git a/plugins/table-example/src/js/package.json b/plugins/table-example/src/js/package.json index 9888d6f6c..e4ade9036 100644 --- a/plugins/table-example/src/js/package.json +++ b/plugins/table-example/src/js/package.json @@ -22,11 +22,11 @@ "@deephaven/jsapi-types": "^0.40.0" }, "devDependencies": { - "@types/react": "^18.0.0", - "react": "^18.0.0" + "@types/react": "^17.0.2", + "react": "^17.0.2" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^17.0.2" }, "publishConfig": { "access": "public" diff --git a/plugins/ui/src/js/package.json b/plugins/ui/src/js/package.json index f209e49c4..087106179 100644 --- a/plugins/ui/src/js/package.json +++ b/plugins/ui/src/js/package.json @@ -36,8 +36,8 @@ "react-dom": "^18.0.0" }, "peerDependencies": { - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + "react": "^18.0.0", + "react-dom": "^18.0.0" }, "dependencies": { "@deephaven/components": "^1.17.0", From fc359d2a31bd8d8f552ce9936f0eeca7665a0095 Mon Sep 17 00:00:00 2001 From: mikebender Date: Mon, 13 Apr 2026 15:01:41 -0400 Subject: [PATCH 11/15] fix: exclude ui plugin from root tsc to avoid React type conflicts The UI plugin uses React 18 / @types/react@18 while the root workspace uses React 17 / @types/react@17. When root tsc type-checks UI plugin files, dependencies at root node_modules resolve react to @types/react@17, causing type mismatch errors. Excluding the UI plugin from root tsc resolves this. The UI plugin still gets type checking via Jest. --- tsconfig.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index e515199a6..7eeb1e05f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,11 @@ "plugins/**/**.jsx", "tests/**/**.ts" ], - "exclude": ["**/node_modules", "plugins/*/src/js/dist/**/*"], + "exclude": [ + "**/node_modules", + "plugins/*/src/js/dist/**/*", + "plugins/ui/src/js/**/*" + ], "watchOptions": { "excludeDirectories": ["**/node_modules", "**/dist"] } From 464c56070d7ba676939a73171ea5eda10d4b054a Mon Sep 17 00:00:00 2001 From: mikebender Date: Mon, 13 Apr 2026 15:35:26 -0400 Subject: [PATCH 12/15] fix: limit lint test workers to 50% of cores to prevent OOM --- jest.config.lint.cjs | 1 + 1 file changed, 1 insertion(+) diff --git a/jest.config.lint.cjs b/jest.config.lint.cjs index a7cf518ce..e64d3d1c8 100644 --- a/jest.config.lint.cjs +++ b/jest.config.lint.cjs @@ -1,4 +1,5 @@ module.exports = { + maxWorkers: '50%', watchPlugins: ['jest-runner-eslint/watch-fix'], projects: [ { From e6edea939a81aa6cc21102ef884c0f66eeb87b83 Mon Sep 17 00:00:00 2001 From: mikebender Date: Mon, 13 Apr 2026 15:41:40 -0400 Subject: [PATCH 13/15] fix: use separate tsconfig for ESLint to include ui plugin files The root tsconfig.json excludes ui plugin files to avoid React type conflicts during tsc. ESLint needs those files included for type-aware linting, so point it to a tsconfig.eslint.json that re-includes them. --- .eslintrc.js | 2 +- tsconfig.eslint.json | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 tsconfig.eslint.json diff --git a/.eslintrc.js b/.eslintrc.js index aad277126..0cf46965b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,7 +5,7 @@ module.exports = { { files: ['**/*.@(ts|tsx)'], parserOptions: { - project: ['./tsconfig.json'], + project: ['./tsconfig.eslint.json'], tsconfigRootDir: __dirname, }, }, diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json new file mode 100644 index 000000000..6400b66ac --- /dev/null +++ b/tsconfig.eslint.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "include": [ + "plugins/**/**.ts", + "plugins/**/**.tsx", + "plugins/**/**.js", + "plugins/**/**.jsx", + "tests/**/**.ts" + ], + "exclude": ["**/node_modules", "plugins/*/src/js/dist/**/*"] +} From 7a5348d1a66ea8492fbfbd5edfa3e76096b204ca Mon Sep 17 00:00:00 2001 From: mikebender Date: Mon, 13 Apr 2026 16:53:02 -0400 Subject: [PATCH 14/15] Fix up styling fix up tests --- plugins/ui/src/js/src/styles.scss | 5 +---- tests/ui_table.spec.ts | 3 ++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/plugins/ui/src/js/src/styles.scss b/plugins/ui/src/js/src/styles.scss index 98dc2b53f..b4c3f1d41 100644 --- a/plugins/ui/src/js/src/styles.scss +++ b/plugins/ui/src/js/src/styles.scss @@ -93,14 +93,11 @@ .dh-panel { .dh-nested-dashboard { + padding: var(--spectrum-global-dimension-size-100); .dashboard-container { border: 1px solid var(--dh-color-bg); } } - &.widget-loader-deephaven\.ui\.Element, - &.widget-loader-deephaven\.ui\.Dashboard { - padding: var(--spectrum-global-dimension-size-100); - } } .ui-text-wrap-balance { diff --git a/tests/ui_table.spec.ts b/tests/ui_table.spec.ts index d273811cd..691c99a9f 100644 --- a/tests/ui_table.spec.ts +++ b/tests/ui_table.spec.ts @@ -1,7 +1,8 @@ import { expect, test } from '@playwright/test'; import { openPanel, gotoPage, clickGridRow } from './utils'; -const REACT_PANEL_VISIBLE = '.dh-react-panel:visible'; +const REACT_PANEL_VISIBLE = + '.dh-panel.widget-loader-deephaven\\.ui\\.Element:visible'; test.describe('UI table', () => { [ From dd4cc5f9f6df54614abe48d78419700a06356fa0 Mon Sep 17 00:00:00 2001 From: mikebender Date: Mon, 13 Apr 2026 19:23:40 -0400 Subject: [PATCH 15/15] fix: update e2e selectors from .dh-react-panel to .dh-panel.widget-loader --- ...hboard-inside-a-panel-1-chromium-linux.png | Bin 4785 -> 6150 bytes ...shboard-inside-a-panel-1-firefox-linux.png | Bin 13249 -> 15393 bytes ...ashboard-inside-a-panel-1-webkit-linux.png | Bin 4781 -> 6189 bytes tests/utils.ts | 5 +++-- 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/ui_nested_dashboard.spec.ts-snapshots/Nested-Dashboards-renders-a-dashboard-inside-a-panel-1-chromium-linux.png b/tests/ui_nested_dashboard.spec.ts-snapshots/Nested-Dashboards-renders-a-dashboard-inside-a-panel-1-chromium-linux.png index 2aa9c0ad657789b41e3fd36524666427895439cb..c4f6c45629d60b62c06df3046b46d1466f1bb05b 100644 GIT binary patch literal 6150 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 literal 4785 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 diff --git a/tests/ui_nested_dashboard.spec.ts-snapshots/Nested-Dashboards-renders-a-dashboard-inside-a-panel-1-firefox-linux.png b/tests/ui_nested_dashboard.spec.ts-snapshots/Nested-Dashboards-renders-a-dashboard-inside-a-panel-1-firefox-linux.png index 30b525479a0cdb9ec65432e041a1cbe8dd047305..6f3c5e873b13c7d45df7c0422dfca7ad23255f8c 100644 GIT binary patch literal 15393 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 AUjP6A literal 13249 zcmeHOXIxX+wm$?A1SyIX1u1q#Kn4{MX(FPdh>oM6RN)FLy_1B5pkqNPIyxePfP;t% zC`gCUq^T$oRC*GM5F{iaQUW9-Z)48!&V6$~y$|o*-|z8>9QHnI|JT}Uuk~MRCoxBl z*vLq&mVzKi=HP*Szd(>U_$Xp5xdi+nQR1Q@NE14^&+^v@7X}$!>U!qS! z%le%5i`O5D-n!(DzUCKZB`#>0SXjFYEyvJ1mlMqYJtce&hi|5#(^y?~K?;q&#O*wJ zO$!1ff)bPb%ZCp?M-Pb+a>ug&{Of<=d6Qyd1a+|b--dLQ z&-K98t6L!t$+pl^4NH?&!3a)^h`6owSFYRlp;$|3*ee?}A+;2esegch0W7=_z}!dC zy%Lk|3#+v3kOgF9l!m4Bd3wUa&jZ`W5S^DPSoT~I>Y{R&00jh?afr3=-@!I&lPcT_ z@wgm5&gbRVp223<-Nw1@(PXD((weLG3azy*IJ$fZfr)PBwFW>!Rnluw2T?Vr3cMQU z=r1%#^X#&Snf|LDlwRq<``Ohy2Yh<`IJKQ)Ymyu8Sjk0o6_xbhdpcQ!n7|RO;{%VQ z1PRNj)zpiqnn%66gzj}p%BO;SRq8YDO+#YUK&ho@&Fmo*K zB?j3|X%VffvvXbs)LuZt`IIOE?%Bkhwpa@Ps)tjq5$dAv6O-E z_e&KTn_^sfk&ze{ZZNUBG%LL~?J97U!=5Ois~pX*X=D0Zvm)N0YUowLxP&h=q&3PM za=0sxpWo!pP4Lmk&Mm&s8%iVVPrc6Y;IoFCPJ8DrH}FhVPjvYf7eNwW>~adf{j5KA zEn~o*L#8HI*LKRdzwN*6@s8eDuT#>ydQ&8`KH}S(tli4p_IUBWC&w}dzGdsiZMiL% zV3l<^o?$lG-^N%~(puWGsv}l|GFSIdK2Mb&>WZ65rt)_ARWrgw+|D~IEdB0C(JxW! zLX9K8@~!zFDz>rEH&8X!UiVCCIrq3l==_mt33docbzids?Bthg4v^WuOAyk`12Mg5 znscBBO))ybbebD6`ZUXZj+Vfv3}VKv@|s4~9MY{YiZ>6#&~jf<<4w);ZE~vSMk~|( z%ZBdWKr5#z2UlVIc=V!*!d@|NO%Q@`2T~rXYbo9Qq`+!+m z3>J^}|7w<7LMdktPf^v(=iiVp-b4mNwW*TRt6I&U5@5S_R-*ED6veDPi61~*7U{>1)@{I8zL zje#E%V&*pT!uzv0j{XHFh;%Y*3>QYdqUxvO z%72?UASxhQv%&{A`K**s-?7E4z3j^rR=ltFw%m0a4crdT2k0=G;hVIDFcu06U}D{?VYBw%qGPRKO|9M7c;G#@|6t zN!Lk5J11{%igEBsnj(RwERP-1VxsE?43gl0uwaA14NIX4SJbz$U{a%~+#Y$?WCO$U z#QJJ9O%S`ryxc1Gbl~L{ZQlMSUjf=tE%b}No+?zuHDz6YBcY+hitM0v?_y7EiwLtEE3DJSi7ssM=6KWLnHhEhUaiMZ@GyePCg%& z%v=q_CY?ET_VbB>Z`yhcqGEXUk@0ZsSl*z`KyK9h-OMEfvOScFnR~<56BMF}9V{t>rH2zrU)0_XtI znmZg~;u3;KV{A-Dg6U6wl|wdxCuzAgm-wYLnXR6CVBAG8?#_lTY?@sI*Lld>8V6J1-mdv95ra}W2LlwZ~e{!|#vE$nyP zH5N&sUb3P>#B2 zGDAfFtg<_wH_NVMkw0-SmWoR&E!(WppK7>0X(@ch8y5T|dk>V;`EYr&G^EyZJqo2Nx{gs5@F8pv6C*UFC}|A+OFoZguJJ$L^#BSG!wk3^ zp|0J9v({E+ko%8}{mb0{?c6U3DWEGEL9jmclPj#=YGfI0Z90idpM$AR`T@dNeZ~ibOf`v88`lX48oAu1y4Y136vbBI5 zO5%;=gsNG%%>dZ_s;8rcp-=O}YG7^e(@*7vS`lh)5}*%t@XPX=<9{~yA2KG2cZ$L^ zNd88W3>5$SE6kAnxMPD+qZGl9z{uKb+kOvz;

Jrqf&JbRS?os^&Ab?*kjo+D|(Nmyp9_7HB|Z=yZw^w%vGLarI@S zFxVn~MFA>iq?XK$d>&kg^lUwcJWV{OVwOFhTtzLTzgNFi;r+I%`-V`z*N&R!AtS%u z(wVnkUE}Hesq)g%XW1T~o*c`cRbnN4w0p2h&YU-%XA<~9>$dy*ogJ|to9!AaQqtKT zPALlv#>e;mu#teW1=pEaguq;O#@3 zdOarJI%mS3Uhg%XrXnDhmBfF+8Jvw`!2A7W%gr6op3ufEY;KeK4U&4;m*xxpJMd12 zd;O`MZkML8QD+!c_n8X}ddKuLZ{393RS`ixMN>-bM#Cz7X0?ES4^ywt9?3{(?9eOI zYPAlt*MrQ^g|1+nSfEt(k1kCoFfY^1 zqwtRY=fe344@#u$x&`So@BQ(rfC8^B=?(HuK{w_&oX=D=iMmBL+@GMn#%7JNPAYmh zDS|&s^Jq6V7@Y25UMq7=R`xJdQ$3zww#TfjgAz#6V==@D!Mmf$wgSFJ;N-E7?hVJZ z8!s!TXP#%}sw8mUVJ)$q#$gg{HV{u0kOmhy4|1M5Y zjU{WgBpGN=cMl#9q^$|pt*zuXg~jC-cl}gM985pz$oupVaNuh@Yk zQ%>V411}kIf(fJ4n>WXI<=~_EmtEhjS)*@~k4;Pn+{>u*Np+6QXsq-vGH92bHM?}BA zu+L+i`TE$FQ|uU1PW%ElUYeGXWy^@fQ?>@y;3Z_{pL4_dYl=LM;2O-vkDM7;`0gPR^`T8i6ikEkpfRSn0i{IFGqoD@_8fRS)o;VgZVAm(`FT7 zM>sk)j((MAeK@rZ6jbC}ffX%SG(mSI6z0k(X+P~PgVXNWnC!PAD+Tk**eu(w z(K(z_RG(_?A`(HF4IX%={Q}?MFJkuX$-03uno@o51fO?VtAbJG&1-PoreUMb&kE+k zZ3@X9*6D|#&UP%NS)6c#Zwqza+0<_x5<%FI+QAuhw>8qJ{7sN=^+u^?z>=o(LtzfD-`V^rL zC+*pAQf22e&X5Kz#l$2P8)g~VUw_+u)?PpfF?N<`H}mmWD-cMd(3?YhQ3a^mGZeD5TsL_%+FmMWlWVEt_<1EP*i8fn~&O>sz~ zREd5m;?~1NldtITmHH}J;FTEoJ^@Nce_dsKO7Bi9XF3r4pLSnebW4g;VZlSu)m>bReq2L?Q z8e-WAJDA8kDX9rS)nM$0Ll8C*3E0N$w963kykUVaNd1#9h!Gg{r`M5ll?i5NemyLt z=3eraqdLpmSDPwgw>|C!{5zY^7o|gc(@^>at{K^D$&x9EcNtxD4rB ze$mu~-aTx-0E-V&0L-R6a0+HNVsi_mOC13^4Tw%p$8kl32mK7zI`lE=0HP^q;^h_R z25v`G!2lYC2{u85Jp*0SlR7>)WcU)$Tjs*u3}jqNN)nRZyJ|ly?zJT#X;z7!Vewx! z0;IWvqX>tcTrLk`_8?Yb0N}+hvbMs-spK87*4@Vjw_ry->Ik6tIu5!as!Rg2Ob&-3 zR{d265X94+bI9-#psDJoZ8peaD_6=xO27T|gFjvZM!%|?4U2yb==43urq739P9V+N&0wu`(S^0{x9mf9$QM8<@{PNMY=%mHGz3Wf*4XPIu9^Ufj6q9St#fHWHqP|Ka%8j+Jnwh_H>jZK zZs085J*y=UM}7oK#>a*wu-X>s7l823uiD|dUvkF*plQ0N@m54!IuNIM=M1vpYQPtb zLr%pBpDp|V(%#+AT@XWPh=`;&!Ci074`x6%7xQc_GI}07pWhAl1VvCqpe$@J-YJVX z@&P^2CinNVL8gBO!k=BvMFPY*P+a9%z7P5p8Mg%DEH~F7{$LEwVDQMx)o?KC1xU+6 zohlLJW}pyCkU-S>k1m831Kam)S`2L8&G2L~uq_<%^u@p?yh~XOY~MqA`u_vQCK(>` z5rPyV7rqOyknb1S8=Sv27unnQn7GK^7ASi3e^eWLk-aUlx5ct_u`GrA8jEEqh|nUa z#eUoOX3t{3O~~MGF815L`@>?t?Ry{d|MrUqi;QiNu`M#TMaH(s*#7l~G}Zxfn6mtF z0kcqQ!~GY6g>iIiM#qRr;P)@fJNTV1K(1ln`B-;PQYyIdLOufR`ppo7*&_C4S0cJaRe+8;u< diff --git a/tests/ui_nested_dashboard.spec.ts-snapshots/Nested-Dashboards-renders-a-dashboard-inside-a-panel-1-webkit-linux.png b/tests/ui_nested_dashboard.spec.ts-snapshots/Nested-Dashboards-renders-a-dashboard-inside-a-panel-1-webkit-linux.png index 57655e3c4535f51efe30343914a4fd7de47b5e44..4a28126ad9f6c4bcd84163b3dae8d2a851ef8d08 100644 GIT binary patch literal 6189 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 L9v7;=2>t%AGY=t~ diff --git a/tests/utils.ts b/tests/utils.ts index cb7962dc2..b957d0c0e 100644 --- a/tests/utils.ts +++ b/tests/utils.ts @@ -2,8 +2,9 @@ import test, { Locator, Page, expect } from '@playwright/test'; import os from 'node:os'; export const SELECTORS = { - REACT_PANEL: '.dh-react-panel', - REACT_PANEL_VISIBLE: '.dh-react-panel:visible', + REACT_PANEL: '.dh-panel.widget-loader-deephaven\\.ui\\.Element', + REACT_PANEL_VISIBLE: + '.dh-panel.widget-loader-deephaven\\.ui\\.Element:visible', REACT_PANEL_OVERLAY: '.dh-react-panel-overlay', };