From 004a347fa870e3175997d9ee4cea1303965b8b8f Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Wed, 11 Jun 2025 10:20:28 -0500 Subject: [PATCH 01/20] wip --- .../app-utils/src/plugins/PluginUtils.tsx | 1 + packages/plugin/src/PluginTypes.ts | 15 ++++++++++++- packages/plugin/src/PluginUtils.tsx | 22 +++++++++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/packages/app-utils/src/plugins/PluginUtils.tsx b/packages/app-utils/src/plugins/PluginUtils.tsx index 0e88c5a7fc..9ea7f7b368 100644 --- a/packages/app-utils/src/plugins/PluginUtils.tsx +++ b/packages/app-utils/src/plugins/PluginUtils.tsx @@ -69,6 +69,7 @@ export function getPluginModuleValue( // whether there are also named exports. If the default is the only // export, it will be the value. If there are also named exports, // it will be assigned to the `default` property on the value. + console.log('getPluginModuleValue', value); if (isPlugin(value)) { return value; } diff --git a/packages/plugin/src/PluginTypes.ts b/packages/plugin/src/PluginTypes.ts index d19b79e61e..e1ccfaf1bd 100644 --- a/packages/plugin/src/PluginTypes.ts +++ b/packages/plugin/src/PluginTypes.ts @@ -6,6 +6,7 @@ import { import type { dh } from '@deephaven/jsapi-types'; import type { IconDefinition } from '@fortawesome/fontawesome-common-types'; import type { TablePluginComponent } from './TablePlugin'; +import exp from 'constants'; export const PluginType = Object.freeze({ AUTH_PLUGIN: 'AuthPlugin', @@ -13,6 +14,7 @@ export const PluginType = Object.freeze({ WIDGET_PLUGIN: 'WidgetPlugin', TABLE_PLUGIN: 'TablePlugin', THEME_PLUGIN: 'ThemePlugin', + ELEMENT_PLUGIN: 'ElementPlugin', }); /** @@ -238,12 +240,23 @@ export function isThemePlugin(plugin: PluginModule): plugin is ThemePlugin { return 'type' in plugin && plugin.type === PluginType.THEME_PLUGIN; } +export interface ElementPlugin extends Plugin { + name: string; + type: typeof PluginType.ELEMENT_PLUGIN; + mapping: Record>; +} + +export function isElementPlugin(plugin: PluginModule): plugin is ElementPlugin { + return 'type' in plugin && plugin.type === PluginType.ELEMENT_PLUGIN; +} + export function isPlugin(plugin: unknown): plugin is Plugin { return ( isDashboardPlugin(plugin as PluginModule) || isAuthPlugin(plugin as PluginModule) || isTablePlugin(plugin as PluginModule) || isThemePlugin(plugin as PluginModule) || - isWidgetPlugin(plugin as PluginModule) + isWidgetPlugin(plugin as PluginModule) || + isElementPlugin(plugin as PluginModule) ); } diff --git a/packages/plugin/src/PluginUtils.tsx b/packages/plugin/src/PluginUtils.tsx index 051aa3d5ed..b3e1450593 100644 --- a/packages/plugin/src/PluginUtils.tsx +++ b/packages/plugin/src/PluginUtils.tsx @@ -9,6 +9,8 @@ import { type PluginModuleMap, type ThemePlugin, isThemePlugin, + isElementPlugin, + ElementPlugin, } from './PluginTypes'; const log = Log.module('@deephaven/plugin.PluginUtils'); @@ -76,3 +78,23 @@ export function getThemeDataFromPlugins( }) .flat(); } + +export function getElementPluginMapping( + pluginMap: PluginModuleMap +): Map> { + const elementPluginEntries = [...pluginMap.entries()].filter( + (entry): entry is [string, ElementPlugin] => + isElementPlugin(entry[1]) && entry[1].mapping != null + ); + + log.debug('Getting element plugin mapping', elementPluginEntries); + + return new Map( + elementPluginEntries.flatMap(([pluginName, plugin]) => + Object.entries(plugin.mapping).map( + ([elementName, elementComponent]) => + [`${elementName}`, elementComponent] as const + ) + ) + ); +} From 72c5edeabec396785f2735f2a97cb5eb9cedb712 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Fri, 13 Jun 2025 10:46:35 -0500 Subject: [PATCH 02/20] wip --- package-lock.json | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6a963c4e41..7306f24b96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11238,9 +11238,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001439", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz", - "integrity": "sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A==", + "version": "1.0.30001722", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001722.tgz", + "integrity": "sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==", "funding": [ { "type": "opencollective", @@ -11249,6 +11249,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -39370,9 +39374,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001439", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001439.tgz", - "integrity": "sha512-1MgUzEkoMO6gKfXflStpYgZDlFM7M/ck/bgfVCACO5vnAf0fXoNVHdWtqGU+MYca+4bL9Z5bpOVmR33cWW9G2A==" + "version": "1.0.30001722", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001722.tgz", + "integrity": "sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==" }, "canvas-fit": { "version": "1.5.0", From 44925e6970fdb3d1e8e6e6d96d9010e56c1b1d1a Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Fri, 27 Jun 2025 14:32:52 -0500 Subject: [PATCH 03/20] wip --- packages/app-utils/src/plugins/PluginUtils.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/app-utils/src/plugins/PluginUtils.tsx b/packages/app-utils/src/plugins/PluginUtils.tsx index 9ea7f7b368..0e88c5a7fc 100644 --- a/packages/app-utils/src/plugins/PluginUtils.tsx +++ b/packages/app-utils/src/plugins/PluginUtils.tsx @@ -69,7 +69,6 @@ export function getPluginModuleValue( // whether there are also named exports. If the default is the only // export, it will be the value. If there are also named exports, // it will be assigned to the `default` property on the value. - console.log('getPluginModuleValue', value); if (isPlugin(value)) { return value; } From 748e14844ae3059e62a596b46a46edb937da66d5 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Mon, 7 Jul 2025 08:54:17 -0500 Subject: [PATCH 04/20] wip --- packages/plugin/src/PluginTypes.ts | 1 - packages/plugin/src/PluginUtils.tsx | 9 +++++-- packages/plugin/src/index.ts | 1 + .../plugin/src/useElementPluginMapping.tsx | 27 +++++++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 packages/plugin/src/useElementPluginMapping.tsx diff --git a/packages/plugin/src/PluginTypes.ts b/packages/plugin/src/PluginTypes.ts index e1ccfaf1bd..b1da27fcce 100644 --- a/packages/plugin/src/PluginTypes.ts +++ b/packages/plugin/src/PluginTypes.ts @@ -6,7 +6,6 @@ import { import type { dh } from '@deephaven/jsapi-types'; import type { IconDefinition } from '@fortawesome/fontawesome-common-types'; import type { TablePluginComponent } from './TablePlugin'; -import exp from 'constants'; export const PluginType = Object.freeze({ AUTH_PLUGIN: 'AuthPlugin', diff --git a/packages/plugin/src/PluginUtils.tsx b/packages/plugin/src/PluginUtils.tsx index b3e1450593..8c99e98847 100644 --- a/packages/plugin/src/PluginUtils.tsx +++ b/packages/plugin/src/PluginUtils.tsx @@ -10,7 +10,7 @@ import { type ThemePlugin, isThemePlugin, isElementPlugin, - ElementPlugin, + type ElementPlugin, } from './PluginTypes'; const log = Log.module('@deephaven/plugin.PluginUtils'); @@ -79,6 +79,11 @@ export function getThemeDataFromPlugins( .flat(); } +/** + * Get a mapping of element names to their React components from the given plugin map. + * @param pluginMap The plugin map to extract element plugins from. + * @returns A Map of element names to their React components. + */ export function getElementPluginMapping( pluginMap: PluginModuleMap ): Map> { @@ -90,7 +95,7 @@ export function getElementPluginMapping( log.debug('Getting element plugin mapping', elementPluginEntries); return new Map( - elementPluginEntries.flatMap(([pluginName, plugin]) => + elementPluginEntries.flatMap(([, plugin]) => Object.entries(plugin.mapping).map( ([elementName, elementComponent]) => [`${elementName}`, elementComponent] as const diff --git a/packages/plugin/src/index.ts b/packages/plugin/src/index.ts index 9fbc8b13c6..ccb27ff1ed 100644 --- a/packages/plugin/src/index.ts +++ b/packages/plugin/src/index.ts @@ -8,3 +8,4 @@ export * from './usePlugins'; export * from './WidgetView'; export * from './PersistentStateContext'; export * from './usePersistentState'; +export * from './useElementPluginMapping'; diff --git a/packages/plugin/src/useElementPluginMapping.tsx b/packages/plugin/src/useElementPluginMapping.tsx new file mode 100644 index 0000000000..9b9cf9c008 --- /dev/null +++ b/packages/plugin/src/useElementPluginMapping.tsx @@ -0,0 +1,27 @@ +import { ComponentType, useMemo } from 'react'; +import { + isDashboardPlugin, + isLegacyDashboardPlugin, + type PluginModuleMap, + type DashboardPlugin, +} from './PluginTypes'; +import { usePlugins } from './usePlugins'; +import { getElementPluginMapping } from './PluginUtils'; + +/** + * Get all ElementPlugin elements from the plugins context + * @returns ElementPlugin mapping as a Map of plugin name to component type + */ +export function useElementPluginMapping(): Map { + // Get all plugins from the context + const plugins = usePlugins(); + + const elementPlugins = useMemo( + () => getElementPluginMapping(plugins), + [plugins] + ); + + return elementPlugins; +} + +export default useElementPluginMapping; From 3d96d9df23fc7c67b96173ecf1c63dd8f69a5275 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Mon, 7 Jul 2025 09:48:58 -0500 Subject: [PATCH 05/20] wip --- packages/plugin/src/PluginUtils.test.tsx | 48 ++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/packages/plugin/src/PluginUtils.test.tsx b/packages/plugin/src/PluginUtils.test.tsx index a600411f97..deb97a2ac8 100644 --- a/packages/plugin/src/PluginUtils.test.tsx +++ b/packages/plugin/src/PluginUtils.test.tsx @@ -4,6 +4,7 @@ import { type ThemeData } from '@deephaven/components'; import { dhTruck, vsPreview } from '@deephaven/icons'; import { type DashboardPlugin, + ElementPlugin, type PluginModule, PluginType, type ThemePlugin, @@ -13,6 +14,7 @@ import { pluginSupportsType, getIconForPlugin, getThemeDataFromPlugins, + getElementPluginMapping, } from './PluginUtils'; function TestWidget() { @@ -32,6 +34,23 @@ const dashboardPlugin: DashboardPlugin = { component: TestWidget, }; +const ElementPluginOne: ElementPlugin = { + name: 'test-element-plugin-one', + type: PluginType.ELEMENT_PLUGIN, + mapping: { + 'test-element-one': TestWidget, + 'test-element-two': TestWidget, + }, +}; + +const ElementPluginTwo: ElementPlugin = { + name: 'test-element-plugin-two', + type: PluginType.ELEMENT_PLUGIN, + mapping: { + 'test-element-three': TestWidget, + }, +}; + test('pluginSupportsType', () => { expect(pluginSupportsType(widgetPlugin, 'test-widget')).toBe(true); expect(pluginSupportsType(widgetPlugin, 'test-widget-two')).toBe(true); @@ -170,3 +189,32 @@ describe('getThemeDataFromPlugins', () => { expect(actual).toEqual(expected); }); }); + +describe('getElementPluginMapping', () => { + it('should return a mapping of element plugins', () => { + const pluginMap = new Map([ + [ElementPluginOne.name, ElementPluginOne], + [ElementPluginTwo.name, ElementPluginTwo], + [dashboardPlugin.name, dashboardPlugin], + [widgetPlugin.name, widgetPlugin], + ]); + + const elementMapping = getElementPluginMapping(pluginMap); + + expect(elementMapping.size).toBe(3); + expect(elementMapping.get('test-element-one')).toBe(TestWidget); + expect(elementMapping.get('test-element-two')).toBe(TestWidget); + expect(elementMapping.get('test-element-three')).toBe(TestWidget); + }); + + it('should return an empty map if no element plugins are present', () => { + const pluginMap = new Map([ + [widgetPlugin.name, widgetPlugin], + [dashboardPlugin.name, dashboardPlugin], + ]); + + const elementMapping = getElementPluginMapping(pluginMap); + + expect(elementMapping.size).toBe(0); + }); +}); From d6841338107acc8cee14ed31600fe60973128c78 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Mon, 7 Jul 2025 10:00:41 -0500 Subject: [PATCH 06/20] wip --- packages/plugin/src/PluginUtils.test.tsx | 2 +- packages/plugin/src/useElementPluginMapping.tsx | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/plugin/src/PluginUtils.test.tsx b/packages/plugin/src/PluginUtils.test.tsx index deb97a2ac8..7ca80ce73f 100644 --- a/packages/plugin/src/PluginUtils.test.tsx +++ b/packages/plugin/src/PluginUtils.test.tsx @@ -4,7 +4,7 @@ import { type ThemeData } from '@deephaven/components'; import { dhTruck, vsPreview } from '@deephaven/icons'; import { type DashboardPlugin, - ElementPlugin, + type ElementPlugin, type PluginModule, PluginType, type ThemePlugin, diff --git a/packages/plugin/src/useElementPluginMapping.tsx b/packages/plugin/src/useElementPluginMapping.tsx index 9b9cf9c008..102ef03efb 100644 --- a/packages/plugin/src/useElementPluginMapping.tsx +++ b/packages/plugin/src/useElementPluginMapping.tsx @@ -1,10 +1,4 @@ -import { ComponentType, useMemo } from 'react'; -import { - isDashboardPlugin, - isLegacyDashboardPlugin, - type PluginModuleMap, - type DashboardPlugin, -} from './PluginTypes'; +import { type ComponentType, useMemo } from 'react'; import { usePlugins } from './usePlugins'; import { getElementPluginMapping } from './PluginUtils'; From 998f7246630db42d0430309775b83a579d684a69 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Mon, 7 Jul 2025 12:46:52 -0500 Subject: [PATCH 07/20] wip --- .../src/UseElementPluginMapping.test.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 packages/plugin/src/UseElementPluginMapping.test.ts diff --git a/packages/plugin/src/UseElementPluginMapping.test.ts b/packages/plugin/src/UseElementPluginMapping.test.ts new file mode 100644 index 0000000000..73d38d7b1a --- /dev/null +++ b/packages/plugin/src/UseElementPluginMapping.test.ts @@ -0,0 +1,28 @@ +import { renderHook } from '@testing-library/react-hooks'; +import { TestUtils } from '@deephaven/test-utils'; +import type { PluginModuleMap } from './PluginTypes'; +import { useElementPluginMapping } from './useElementPluginMapping'; +import { getElementPluginMapping } from './PluginUtils'; +import { usePlugins } from './usePlugins'; + +jest.mock('@deephaven/components'); +jest.mock('./PluginUtils'); + +const { asMock } = TestUtils; + +const mockElementPluginMapping = new Map< + string, + React.ComponentType +>(); + +const mockPlugins: PluginModuleMap = new Map(); + +it('should return element plugin mapping from plugins context', () => { + asMock(getElementPluginMapping).mockReturnValue(mockElementPluginMapping); + asMock(usePlugins).mockReturnValue(mockPlugins); + + const { result } = renderHook(() => useElementPluginMapping()); + + expect(getElementPluginMapping).toHaveBeenCalledWith(mockPlugins); + expect(result).toEqual(mockElementPluginMapping); +}); From 4e9b5c94188b8f76e6e96e9a1768d43c840bb5eb Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Mon, 7 Jul 2025 13:52:18 -0500 Subject: [PATCH 08/20] wip --- packages/plugin/src/UseElementPluginMapping.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/src/UseElementPluginMapping.test.ts b/packages/plugin/src/UseElementPluginMapping.test.ts index 73d38d7b1a..436c1a03ed 100644 --- a/packages/plugin/src/UseElementPluginMapping.test.ts +++ b/packages/plugin/src/UseElementPluginMapping.test.ts @@ -5,8 +5,8 @@ import { useElementPluginMapping } from './useElementPluginMapping'; import { getElementPluginMapping } from './PluginUtils'; import { usePlugins } from './usePlugins'; -jest.mock('@deephaven/components'); jest.mock('./PluginUtils'); +jest.mock('./usePlugins'); const { asMock } = TestUtils; @@ -24,5 +24,5 @@ it('should return element plugin mapping from plugins context', () => { const { result } = renderHook(() => useElementPluginMapping()); expect(getElementPluginMapping).toHaveBeenCalledWith(mockPlugins); - expect(result).toEqual(mockElementPluginMapping); + expect(result.current).toEqual(mockElementPluginMapping); }); From 8975d561da70cbc3ae015fef09e763669fa3e73e Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Wed, 9 Jul 2025 16:00:55 -0500 Subject: [PATCH 09/20] wip --- packages/plugin/src/PluginTypes.ts | 10 ++++++++-- packages/plugin/src/PluginUtils.test.tsx | 8 ++++---- packages/plugin/src/PluginUtils.tsx | 12 +++--------- packages/plugin/src/UseElementPluginMapping.test.ts | 6 +++--- packages/plugin/src/useElementPluginMapping.tsx | 12 +++++------- 5 files changed, 23 insertions(+), 25 deletions(-) diff --git a/packages/plugin/src/PluginTypes.ts b/packages/plugin/src/PluginTypes.ts index b1da27fcce..961f297468 100644 --- a/packages/plugin/src/PluginTypes.ts +++ b/packages/plugin/src/PluginTypes.ts @@ -6,6 +6,7 @@ import { import type { dh } from '@deephaven/jsapi-types'; import type { IconDefinition } from '@fortawesome/fontawesome-common-types'; import type { TablePluginComponent } from './TablePlugin'; +import { ComponentType } from 'node_modules/@types/react'; export const PluginType = Object.freeze({ AUTH_PLUGIN: 'AuthPlugin', @@ -239,10 +240,15 @@ export function isThemePlugin(plugin: PluginModule): plugin is ThemePlugin { return 'type' in plugin && plugin.type === PluginType.THEME_PLUGIN; } +export type ElementName = string; + +export type ElementPluginMappingDefinition = Record; + +export type ElementMap = ReadonlyMap; + export interface ElementPlugin extends Plugin { - name: string; type: typeof PluginType.ELEMENT_PLUGIN; - mapping: Record>; + mapping: ElementPluginMappingDefinition; } export function isElementPlugin(plugin: PluginModule): plugin is ElementPlugin { diff --git a/packages/plugin/src/PluginUtils.test.tsx b/packages/plugin/src/PluginUtils.test.tsx index 7ca80ce73f..f520653bd5 100644 --- a/packages/plugin/src/PluginUtils.test.tsx +++ b/packages/plugin/src/PluginUtils.test.tsx @@ -14,7 +14,7 @@ import { pluginSupportsType, getIconForPlugin, getThemeDataFromPlugins, - getElementPluginMapping, + getElementPluginMap, } from './PluginUtils'; function TestWidget() { @@ -190,7 +190,7 @@ describe('getThemeDataFromPlugins', () => { }); }); -describe('getElementPluginMapping', () => { +describe('getElementPluginMap', () => { it('should return a mapping of element plugins', () => { const pluginMap = new Map([ [ElementPluginOne.name, ElementPluginOne], @@ -199,7 +199,7 @@ describe('getElementPluginMapping', () => { [widgetPlugin.name, widgetPlugin], ]); - const elementMapping = getElementPluginMapping(pluginMap); + const elementMapping = getElementPluginMap(pluginMap); expect(elementMapping.size).toBe(3); expect(elementMapping.get('test-element-one')).toBe(TestWidget); @@ -213,7 +213,7 @@ describe('getElementPluginMapping', () => { [dashboardPlugin.name, dashboardPlugin], ]); - const elementMapping = getElementPluginMapping(pluginMap); + const elementMapping = getElementPluginMap(pluginMap); expect(elementMapping.size).toBe(0); }); diff --git a/packages/plugin/src/PluginUtils.tsx b/packages/plugin/src/PluginUtils.tsx index 8c99e98847..27758e33da 100644 --- a/packages/plugin/src/PluginUtils.tsx +++ b/packages/plugin/src/PluginUtils.tsx @@ -11,6 +11,7 @@ import { isThemePlugin, isElementPlugin, type ElementPlugin, + ElementMap, } from './PluginTypes'; const log = Log.module('@deephaven/plugin.PluginUtils'); @@ -84,9 +85,7 @@ export function getThemeDataFromPlugins( * @param pluginMap The plugin map to extract element plugins from. * @returns A Map of element names to their React components. */ -export function getElementPluginMapping( - pluginMap: PluginModuleMap -): Map> { +export function getElementPluginMap(pluginMap: PluginModuleMap): ElementMap { const elementPluginEntries = [...pluginMap.entries()].filter( (entry): entry is [string, ElementPlugin] => isElementPlugin(entry[1]) && entry[1].mapping != null @@ -95,11 +94,6 @@ export function getElementPluginMapping( log.debug('Getting element plugin mapping', elementPluginEntries); return new Map( - elementPluginEntries.flatMap(([, plugin]) => - Object.entries(plugin.mapping).map( - ([elementName, elementComponent]) => - [`${elementName}`, elementComponent] as const - ) - ) + elementPluginEntries.flatMap(([, plugin]) => Object.entries(plugin.mapping)) ); } diff --git a/packages/plugin/src/UseElementPluginMapping.test.ts b/packages/plugin/src/UseElementPluginMapping.test.ts index 436c1a03ed..c168c964e1 100644 --- a/packages/plugin/src/UseElementPluginMapping.test.ts +++ b/packages/plugin/src/UseElementPluginMapping.test.ts @@ -2,7 +2,7 @@ import { renderHook } from '@testing-library/react-hooks'; import { TestUtils } from '@deephaven/test-utils'; import type { PluginModuleMap } from './PluginTypes'; import { useElementPluginMapping } from './useElementPluginMapping'; -import { getElementPluginMapping } from './PluginUtils'; +import { getElementPluginMap } from './PluginUtils'; import { usePlugins } from './usePlugins'; jest.mock('./PluginUtils'); @@ -18,11 +18,11 @@ const mockElementPluginMapping = new Map< const mockPlugins: PluginModuleMap = new Map(); it('should return element plugin mapping from plugins context', () => { - asMock(getElementPluginMapping).mockReturnValue(mockElementPluginMapping); + asMock(getElementPluginMap).mockReturnValue(mockElementPluginMapping); asMock(usePlugins).mockReturnValue(mockPlugins); const { result } = renderHook(() => useElementPluginMapping()); - expect(getElementPluginMapping).toHaveBeenCalledWith(mockPlugins); + expect(getElementPluginMap).toHaveBeenCalledWith(mockPlugins); expect(result.current).toEqual(mockElementPluginMapping); }); diff --git a/packages/plugin/src/useElementPluginMapping.tsx b/packages/plugin/src/useElementPluginMapping.tsx index 102ef03efb..a5726ec4fd 100644 --- a/packages/plugin/src/useElementPluginMapping.tsx +++ b/packages/plugin/src/useElementPluginMapping.tsx @@ -1,19 +1,17 @@ -import { type ComponentType, useMemo } from 'react'; +import { useMemo } from 'react'; import { usePlugins } from './usePlugins'; -import { getElementPluginMapping } from './PluginUtils'; +import { getElementPluginMap } from './PluginUtils'; +import { ElementMap } from './PluginTypes'; /** * Get all ElementPlugin elements from the plugins context * @returns ElementPlugin mapping as a Map of plugin name to component type */ -export function useElementPluginMapping(): Map { +export function useElementPluginMapping(): ElementMap { // Get all plugins from the context const plugins = usePlugins(); - const elementPlugins = useMemo( - () => getElementPluginMapping(plugins), - [plugins] - ); + const elementPlugins = useMemo(() => getElementPluginMap(plugins), [plugins]); return elementPlugins; } From dcad4fb64dfc585a8a1371e20da8fe7332dec274 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Wed, 9 Jul 2025 17:19:17 -0500 Subject: [PATCH 10/20] wip --- packages/plugin/src/PluginTypes.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/plugin/src/PluginTypes.ts b/packages/plugin/src/PluginTypes.ts index 961f297468..ce9ef359a0 100644 --- a/packages/plugin/src/PluginTypes.ts +++ b/packages/plugin/src/PluginTypes.ts @@ -6,7 +6,6 @@ import { import type { dh } from '@deephaven/jsapi-types'; import type { IconDefinition } from '@fortawesome/fontawesome-common-types'; import type { TablePluginComponent } from './TablePlugin'; -import { ComponentType } from 'node_modules/@types/react'; export const PluginType = Object.freeze({ AUTH_PLUGIN: 'AuthPlugin', @@ -242,9 +241,12 @@ export function isThemePlugin(plugin: PluginModule): plugin is ThemePlugin { export type ElementName = string; -export type ElementPluginMappingDefinition = Record; +export type ElementPluginMappingDefinition = Record< + ElementName, + React.ComponentType +>; -export type ElementMap = ReadonlyMap; +export type ElementMap = ReadonlyMap; export interface ElementPlugin extends Plugin { type: typeof PluginType.ELEMENT_PLUGIN; From e05bf46a96cc5d897402a002d11407e46e5a55dd Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Wed, 9 Jul 2025 17:27:02 -0500 Subject: [PATCH 11/20] wip --- packages/plugin/src/PluginUtils.tsx | 2 +- packages/plugin/src/useElementPluginMapping.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin/src/PluginUtils.tsx b/packages/plugin/src/PluginUtils.tsx index 27758e33da..d75c7feb8c 100644 --- a/packages/plugin/src/PluginUtils.tsx +++ b/packages/plugin/src/PluginUtils.tsx @@ -11,7 +11,7 @@ import { isThemePlugin, isElementPlugin, type ElementPlugin, - ElementMap, + type ElementMap, } from './PluginTypes'; const log = Log.module('@deephaven/plugin.PluginUtils'); diff --git a/packages/plugin/src/useElementPluginMapping.tsx b/packages/plugin/src/useElementPluginMapping.tsx index a5726ec4fd..561966e65e 100644 --- a/packages/plugin/src/useElementPluginMapping.tsx +++ b/packages/plugin/src/useElementPluginMapping.tsx @@ -1,7 +1,7 @@ import { useMemo } from 'react'; import { usePlugins } from './usePlugins'; import { getElementPluginMap } from './PluginUtils'; -import { ElementMap } from './PluginTypes'; +import type { ElementMap } from './PluginTypes'; /** * Get all ElementPlugin elements from the plugins context From 5a81898419396a25d41f3a6e0ad3ecb9ccc12928 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Wed, 9 Jul 2025 19:22:27 -0500 Subject: [PATCH 12/20] wip --- packages/plugin/src/PluginTypes.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/plugin/src/PluginTypes.ts b/packages/plugin/src/PluginTypes.ts index ce9ef359a0..49b9892fdd 100644 --- a/packages/plugin/src/PluginTypes.ts +++ b/packages/plugin/src/PluginTypes.ts @@ -248,6 +248,9 @@ export type ElementPluginMappingDefinition = Record< export type ElementMap = ReadonlyMap; +/** An element plugin is used by deephaven.ui to render custom components + * The mapping contains the element names as keys and the React components as values. + */ export interface ElementPlugin extends Plugin { type: typeof PluginType.ELEMENT_PLUGIN; mapping: ElementPluginMappingDefinition; From de2a3187c0b08d83aa99c6c9ff4e012ed87aee28 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Wed, 9 Jul 2025 19:23:26 -0500 Subject: [PATCH 13/20] wip --- packages/plugin/src/PluginTypes.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/plugin/src/PluginTypes.ts b/packages/plugin/src/PluginTypes.ts index 49b9892fdd..b1356d76b2 100644 --- a/packages/plugin/src/PluginTypes.ts +++ b/packages/plugin/src/PluginTypes.ts @@ -241,6 +241,7 @@ export function isThemePlugin(plugin: PluginModule): plugin is ThemePlugin { export type ElementName = string; +/** A mapping of element names to their React components. */ export type ElementPluginMappingDefinition = Record< ElementName, React.ComponentType From a95ac166af77ec5970257792f481d4c0c588df37 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Thu, 10 Jul 2025 10:56:46 -0500 Subject: [PATCH 14/20] wip --- ...ementPluginMapping.test.ts => useElementPluginMapping.test.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/plugin/src/{UseElementPluginMapping.test.ts => useElementPluginMapping.test.ts} (100%) diff --git a/packages/plugin/src/UseElementPluginMapping.test.ts b/packages/plugin/src/useElementPluginMapping.test.ts similarity index 100% rename from packages/plugin/src/UseElementPluginMapping.test.ts rename to packages/plugin/src/useElementPluginMapping.test.ts From 24f7803d6cccb7d98eac982f4adacbd86c0fc792 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Thu, 10 Jul 2025 11:21:39 -0500 Subject: [PATCH 15/20] wip --- packages/plugin/src/PluginUtils.tsx | 2 +- packages/plugin/src/useElementPluginMapping.test.ts | 10 +++++----- packages/plugin/src/useElementPluginMapping.tsx | 11 +++++++---- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/plugin/src/PluginUtils.tsx b/packages/plugin/src/PluginUtils.tsx index d75c7feb8c..e4ea1fa617 100644 --- a/packages/plugin/src/PluginUtils.tsx +++ b/packages/plugin/src/PluginUtils.tsx @@ -85,7 +85,7 @@ export function getThemeDataFromPlugins( * @param pluginMap The plugin map to extract element plugins from. * @returns A Map of element names to their React components. */ -export function getElementPluginMap(pluginMap: PluginModuleMap): ElementMap { +export function getPluginsElementMap(pluginMap: PluginModuleMap): ElementMap { const elementPluginEntries = [...pluginMap.entries()].filter( (entry): entry is [string, ElementPlugin] => isElementPlugin(entry[1]) && entry[1].mapping != null diff --git a/packages/plugin/src/useElementPluginMapping.test.ts b/packages/plugin/src/useElementPluginMapping.test.ts index c168c964e1..38674f6820 100644 --- a/packages/plugin/src/useElementPluginMapping.test.ts +++ b/packages/plugin/src/useElementPluginMapping.test.ts @@ -1,8 +1,8 @@ import { renderHook } from '@testing-library/react-hooks'; import { TestUtils } from '@deephaven/test-utils'; import type { PluginModuleMap } from './PluginTypes'; -import { useElementPluginMapping } from './useElementPluginMapping'; -import { getElementPluginMap } from './PluginUtils'; +import { usePluginsElementMap } from './useElementPluginMapping'; +import { getPluginsElementMap } from './PluginUtils'; import { usePlugins } from './usePlugins'; jest.mock('./PluginUtils'); @@ -18,11 +18,11 @@ const mockElementPluginMapping = new Map< const mockPlugins: PluginModuleMap = new Map(); it('should return element plugin mapping from plugins context', () => { - asMock(getElementPluginMap).mockReturnValue(mockElementPluginMapping); + asMock(getPluginsElementMap).mockReturnValue(mockElementPluginMapping); asMock(usePlugins).mockReturnValue(mockPlugins); - const { result } = renderHook(() => useElementPluginMapping()); + const { result } = renderHook(() => usePluginsElementMap()); - expect(getElementPluginMap).toHaveBeenCalledWith(mockPlugins); + expect(getPluginsElementMap).toHaveBeenCalledWith(mockPlugins); expect(result.current).toEqual(mockElementPluginMapping); }); diff --git a/packages/plugin/src/useElementPluginMapping.tsx b/packages/plugin/src/useElementPluginMapping.tsx index 561966e65e..f91f737d9f 100644 --- a/packages/plugin/src/useElementPluginMapping.tsx +++ b/packages/plugin/src/useElementPluginMapping.tsx @@ -1,19 +1,22 @@ import { useMemo } from 'react'; import { usePlugins } from './usePlugins'; -import { getElementPluginMap } from './PluginUtils'; +import { getPluginsElementMap } from './PluginUtils'; import type { ElementMap } from './PluginTypes'; /** * Get all ElementPlugin elements from the plugins context * @returns ElementPlugin mapping as a Map of plugin name to component type */ -export function useElementPluginMapping(): ElementMap { +export function usePluginsElementMap(): ElementMap { // Get all plugins from the context const plugins = usePlugins(); - const elementPlugins = useMemo(() => getElementPluginMap(plugins), [plugins]); + const elementPlugins = useMemo( + () => getPluginsElementMap(plugins), + [plugins] + ); return elementPlugins; } -export default useElementPluginMapping; +export default usePluginsElementMap; From 1f9ebc43fadcac50e47cb2ad80227b4362650bff Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Thu, 10 Jul 2025 11:29:04 -0500 Subject: [PATCH 16/20] wip --- packages/plugin/src/PluginUtils.test.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/plugin/src/PluginUtils.test.tsx b/packages/plugin/src/PluginUtils.test.tsx index f520653bd5..0d9f6afef2 100644 --- a/packages/plugin/src/PluginUtils.test.tsx +++ b/packages/plugin/src/PluginUtils.test.tsx @@ -14,7 +14,7 @@ import { pluginSupportsType, getIconForPlugin, getThemeDataFromPlugins, - getElementPluginMap, + getPluginsElementMap, } from './PluginUtils'; function TestWidget() { @@ -199,7 +199,7 @@ describe('getElementPluginMap', () => { [widgetPlugin.name, widgetPlugin], ]); - const elementMapping = getElementPluginMap(pluginMap); + const elementMapping = getPluginsElementMap(pluginMap); expect(elementMapping.size).toBe(3); expect(elementMapping.get('test-element-one')).toBe(TestWidget); @@ -213,7 +213,7 @@ describe('getElementPluginMap', () => { [dashboardPlugin.name, dashboardPlugin], ]); - const elementMapping = getElementPluginMap(pluginMap); + const elementMapping = getPluginsElementMap(pluginMap); expect(elementMapping.size).toBe(0); }); From 003027cba60cdc0f5cd26aab8bc41bde821464c9 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Mon, 14 Jul 2025 14:37:20 -0500 Subject: [PATCH 17/20] fix file name --- ...eElementPluginMapping.test.ts => usePluginsElementMap.test.ts} | 0 .../src/{useElementPluginMapping.tsx => usePluginsElementMap.tsx} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/plugin/src/{useElementPluginMapping.test.ts => usePluginsElementMap.test.ts} (100%) rename packages/plugin/src/{useElementPluginMapping.tsx => usePluginsElementMap.tsx} (100%) diff --git a/packages/plugin/src/useElementPluginMapping.test.ts b/packages/plugin/src/usePluginsElementMap.test.ts similarity index 100% rename from packages/plugin/src/useElementPluginMapping.test.ts rename to packages/plugin/src/usePluginsElementMap.test.ts diff --git a/packages/plugin/src/useElementPluginMapping.tsx b/packages/plugin/src/usePluginsElementMap.tsx similarity index 100% rename from packages/plugin/src/useElementPluginMapping.tsx rename to packages/plugin/src/usePluginsElementMap.tsx From 9b0bf6bb34f0ad347e393eaf22a7730276e38dc1 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Mon, 14 Jul 2025 14:42:18 -0500 Subject: [PATCH 18/20] fix index --- packages/plugin/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin/src/index.ts b/packages/plugin/src/index.ts index ccb27ff1ed..fdbdb315d3 100644 --- a/packages/plugin/src/index.ts +++ b/packages/plugin/src/index.ts @@ -8,4 +8,4 @@ export * from './usePlugins'; export * from './WidgetView'; export * from './PersistentStateContext'; export * from './usePersistentState'; -export * from './useElementPluginMapping'; +export * from './usePluginsElementMap'; From 160661d60efd89f4d05598e08714bd0c1f1a721a Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Mon, 14 Jul 2025 14:49:23 -0500 Subject: [PATCH 19/20] fix package lock --- package-lock.json | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3c86906213..4e78e866b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11590,15 +11590,9 @@ } }, "node_modules/caniuse-lite": { -<<<<<<< HEAD "version": "1.0.30001722", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001722.tgz", "integrity": "sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==", -======= - "version": "1.0.30001720", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001720.tgz", - "integrity": "sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==", ->>>>>>> origin/main "funding": [ { "type": "opencollective", @@ -41120,15 +41114,9 @@ } }, "caniuse-lite": { -<<<<<<< HEAD "version": "1.0.30001722", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001722.tgz", "integrity": "sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==" -======= - "version": "1.0.30001720", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001720.tgz", - "integrity": "sha512-Ec/2yV2nNPwb4DnTANEV99ZWwm3ZWfdlfkQbWSDDt+PsXEVYwlhPH8tdMaPunYTKKmz7AnHi2oNEi1GcmKCD8g==" ->>>>>>> origin/main }, "canvas-fit": { "version": "1.5.0", From e783149315d23e67f95bedb1e014a39dc2574af2 Mon Sep 17 00:00:00 2001 From: Joe Numainville Date: Mon, 14 Jul 2025 14:56:02 -0500 Subject: [PATCH 20/20] fix import --- packages/plugin/src/usePluginsElementMap.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin/src/usePluginsElementMap.test.ts b/packages/plugin/src/usePluginsElementMap.test.ts index 38674f6820..00f38d5774 100644 --- a/packages/plugin/src/usePluginsElementMap.test.ts +++ b/packages/plugin/src/usePluginsElementMap.test.ts @@ -1,7 +1,7 @@ import { renderHook } from '@testing-library/react-hooks'; import { TestUtils } from '@deephaven/test-utils'; import type { PluginModuleMap } from './PluginTypes'; -import { usePluginsElementMap } from './useElementPluginMapping'; +import { usePluginsElementMap } from './usePluginsElementMap'; import { getPluginsElementMap } from './PluginUtils'; import { usePlugins } from './usePlugins';