From 32d09e8a94d33cef7e2a0bb98c53f3e74211149b Mon Sep 17 00:00:00 2001 From: Matthew Runyon Date: Fri, 28 Jun 2024 16:26:30 -0500 Subject: [PATCH] feat: ui.table context menu items (#522) Fixes #321 Here's an example with a context menu item on the row and a sub-menu action item on the header ```py from deephaven import empty_table, time_table, ui @ui.component def my_comp(): t = time_table("PT1S").update(["X=i", "Y=i"]) return ui.table( t, context_items=[{ "title": "Test", "action": lambda d: print(d)}], context_column_header_items=[ { "title": "Header", "actions": [{ "title": "Header-sub", "action": lambda d: print(d)}] } ] ) c = my_comp() ``` --- package-lock.json | 1138 +++++++++-------- plugins/ui/DESIGN.md | 211 ++- plugins/ui/docs/README.md | 72 ++ .../ui/src/deephaven/ui/components/table.py | 13 + .../ui/src/deephaven/ui/elements/UITable.py | 40 - plugins/ui/src/deephaven/ui/types/types.py | 115 +- plugins/ui/src/js/package.json | 30 +- plugins/ui/src/js/src/elements/UITable.tsx | 47 +- .../utils/UITableContextMenuHandler.ts | 68 + .../js/src/elements/utils/UITableUtils.tsx | 103 +- plugins/ui/src/ui.schema.json | 40 +- 11 files changed, 1214 insertions(+), 663 deletions(-) create mode 100644 plugins/ui/src/js/src/elements/utils/UITableContextMenuHandler.ts diff --git a/package-lock.json b/package-lock.json index e71796cbf..e6277070f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26252,7 +26252,8 @@ }, "node_modules/proxy-compare": { "version": "3.0.0", - "license": "MIT" + "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-3.0.0.tgz", + "integrity": "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w==" }, "node_modules/proxy-from-env": { "version": "1.1.0", @@ -26261,7 +26262,8 @@ }, "node_modules/proxy-memoize": { "version": "3.0.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/proxy-memoize/-/proxy-memoize-3.0.0.tgz", + "integrity": "sha512-2fs4eIg4w6SfOjKHGVdg5tJ9WgHifEXKo2gfS/+tHGajO2YtAu03lLs+ltNKnteGKvq3SvHromkZeKus4J39/g==", "dependencies": { "proxy-compare": "^3.0.0" } @@ -32185,21 +32187,21 @@ "version": "0.16.0", "license": "Apache-2.0", "dependencies": { - "@deephaven/chart": "^0.81.1", - "@deephaven/components": "^0.81.1", - "@deephaven/dashboard": "^0.81.1", - "@deephaven/dashboard-core-plugins": "^0.81.1", - "@deephaven/grid": "^0.81.0", - "@deephaven/icons": "^0.81.0", - "@deephaven/iris-grid": "^0.81.1", - "@deephaven/jsapi-bootstrap": "^0.81.1", - "@deephaven/jsapi-components": "^0.81.1", - "@deephaven/jsapi-types": "^1.0.0-dev0.34.3", - "@deephaven/log": "^0.81.0", - "@deephaven/plugin": "^0.81.1", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/redux": "^0.81.1", - "@deephaven/utils": "^0.81.0", + "@deephaven/chart": "^0.84.0", + "@deephaven/components": "^0.84.0", + "@deephaven/dashboard": "^0.84.0", + "@deephaven/dashboard-core-plugins": "^0.84.0", + "@deephaven/grid": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/iris-grid": "^0.84.0", + "@deephaven/jsapi-bootstrap": "^0.84.0", + "@deephaven/jsapi-components": "^0.84.0", + "@deephaven/jsapi-types": "^1.0.0-dev0.35.0", + "@deephaven/log": "^0.84.0", + "@deephaven/plugin": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/redux": "^0.84.0", + "@deephaven/utils": "^0.84.0", "@fortawesome/react-fontawesome": "^0.2.0", "@react-types/shared": "^3.22.0", "classnames": "^2.5.1", @@ -32220,83 +32222,18 @@ "react-dom": "^17.0.2" } }, - "plugins/ui/src/js/node_modules/@adobe/react-spectrum": { - "version": "3.33.1", - "license": "Apache-2.0", - "dependencies": { - "@internationalized/string": "^3.2.0", - "@react-aria/i18n": "^3.10.0", - "@react-aria/ssr": "^3.9.1", - "@react-aria/utils": "^3.23.0", - "@react-aria/visually-hidden": "^3.8.8", - "@react-spectrum/actionbar": "^3.4.1", - "@react-spectrum/actiongroup": "^3.10.1", - "@react-spectrum/avatar": "^3.0.8", - "@react-spectrum/badge": "^3.1.9", - "@react-spectrum/breadcrumbs": "^3.9.3", - "@react-spectrum/button": "^3.16.0", - "@react-spectrum/buttongroup": "^3.6.9", - "@react-spectrum/calendar": "^3.4.5", - "@react-spectrum/checkbox": "^3.9.2", - "@react-spectrum/combobox": "^3.12.1", - "@react-spectrum/contextualhelp": "^3.6.7", - "@react-spectrum/datepicker": "^3.9.2", - "@react-spectrum/dialog": "^3.8.7", - "@react-spectrum/divider": "^3.5.9", - "@react-spectrum/dnd": "^3.3.6", - "@react-spectrum/form": "^3.7.2", - "@react-spectrum/icon": "^3.7.9", - "@react-spectrum/illustratedmessage": "^3.4.9", - "@react-spectrum/image": "^3.4.9", - "@react-spectrum/inlinealert": "^3.2.1", - "@react-spectrum/labeledvalue": "^3.1.10", - "@react-spectrum/layout": "^3.6.1", - "@react-spectrum/link": "^3.6.3", - "@react-spectrum/list": "^3.7.6", - "@react-spectrum/listbox": "^3.12.5", - "@react-spectrum/menu": "^3.17.0", - "@react-spectrum/meter": "^3.4.9", - "@react-spectrum/numberfield": "^3.8.2", - "@react-spectrum/overlays": "^5.5.3", - "@react-spectrum/picker": "^3.14.1", - "@react-spectrum/progress": "^3.7.3", - "@react-spectrum/provider": "^3.9.3", - "@react-spectrum/radio": "^3.7.2", - "@react-spectrum/searchfield": "^3.8.2", - "@react-spectrum/slider": "^3.6.5", - "@react-spectrum/statuslight": "^3.5.9", - "@react-spectrum/switch": "^3.5.1", - "@react-spectrum/table": "^3.12.6", - "@react-spectrum/tabs": "^3.8.6", - "@react-spectrum/tag": "^3.2.2", - "@react-spectrum/text": "^3.5.1", - "@react-spectrum/textfield": "^3.11.2", - "@react-spectrum/theme-dark": "^3.5.7", - "@react-spectrum/theme-default": "^3.5.7", - "@react-spectrum/theme-light": "^3.4.7", - "@react-spectrum/tooltip": "^3.6.3", - "@react-spectrum/view": "^3.6.6", - "@react-spectrum/well": "^3.4.9", - "@react-stately/collections": "^3.10.4", - "@react-stately/data": "^3.11.0", - "@react-types/shared": "^3.22.0" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0" - } - }, "plugins/ui/src/js/node_modules/@deephaven/chart": { - "version": "0.81.1", - "license": "Apache-2.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/chart/-/chart-0.84.0.tgz", + "integrity": "sha512-UUtwO27zr8m213ZTmmO/Xv9XL28phSIb/OLBSpKtbW4iL+rXdzFf3t42q7kGfukXf4MUG2i+CyG/GKiKe+3vZw==", "dependencies": { - "@deephaven/components": "^0.81.1", - "@deephaven/icons": "^0.81.0", + "@deephaven/components": "^0.84.0", + "@deephaven/icons": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/jsapi-utils": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@deephaven/jsapi-utils": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/utils": "^0.84.0", "buffer": "^6.0.3", "fast-deep-equal": "^3.1.3", "lodash.debounce": "^4.0.8", @@ -32319,14 +32256,15 @@ "license": "Apache-2.0" }, "plugins/ui/src/js/node_modules/@deephaven/components": { - "version": "0.81.1", - "license": "Apache-2.0", - "dependencies": { - "@adobe/react-spectrum": "3.33.1", - "@deephaven/icons": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/components/-/components-0.84.0.tgz", + "integrity": "sha512-3lUz+JGQQMxdG9MmQbReHfWr4h0FiIOJtH17DIQnelYP+VDoiqWFfg4c/uEs7EMRIQAtKi8NI88DrXzoEwhS7w==", + "dependencies": { + "@adobe/react-spectrum": "3.35.1", + "@deephaven/icons": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/utils": "^0.84.0", "@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/react-fontawesome": "^0.2.0", "@react-spectrum/theme-default": "^3.5.1", @@ -32357,55 +32295,17 @@ "react-dom": ">=16.8.0" } }, - "plugins/ui/src/js/node_modules/@deephaven/console": { - "version": "0.81.1", - "license": "Apache-2.0", - "dependencies": { - "@deephaven/chart": "^0.81.1", - "@deephaven/components": "^0.81.1", - "@deephaven/icons": "^0.81.0", - "@deephaven/jsapi-bootstrap": "^0.81.1", - "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/storage": "^0.81.0", - "@deephaven/utils": "^0.81.0", - "@fortawesome/react-fontawesome": "^0.2.0", - "classnames": "^2.3.1", - "linkifyjs": "^4.1.0", - "lodash.debounce": "^4.0.8", - "lodash.throttle": "^4.1.1", - "memoize-one": "^5.1.1", - "memoizee": "^0.4.15", - "monaco-editor": "^0.41.0", - "nanoid": "^5.0.7", - "papaparse": "5.3.2", - "popper.js": "^1.16.1", - "prop-types": "^15.7.2", - "shell-quote": "^1.7.2" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "plugins/ui/src/js/node_modules/@deephaven/console/node_modules/@deephaven/jsapi-types": { - "version": "1.0.0-dev0.34.0", - "license": "Apache-2.0" - }, "plugins/ui/src/js/node_modules/@deephaven/dashboard": { - "version": "0.81.1", - "license": "Apache-2.0", - "dependencies": { - "@deephaven/components": "^0.81.1", - "@deephaven/golden-layout": "^0.81.1", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/redux": "^0.81.1", - "@deephaven/utils": "^0.81.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/dashboard/-/dashboard-0.84.0.tgz", + "integrity": "sha512-AsYI6ppk0OtB3p/S+VVMuWO/RJJ/V3XcLQsBy5oA1GG+2sD6AMjtFG5QbTGQopI995UPEcUWnLODWr3CcPItQg==", + "dependencies": { + "@deephaven/components": "^0.84.0", + "@deephaven/golden-layout": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/redux": "^0.84.0", + "@deephaven/utils": "^0.84.0", "fast-deep-equal": "^3.1.3", "lodash.ismatch": "^4.1.1", "lodash.throttle": "^4.1.1", @@ -32423,29 +32323,30 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/dashboard-core-plugins": { - "version": "0.81.1", - "license": "Apache-2.0", - "dependencies": { - "@deephaven/chart": "^0.81.1", - "@deephaven/components": "^0.81.1", - "@deephaven/console": "^0.81.1", - "@deephaven/dashboard": "^0.81.1", - "@deephaven/file-explorer": "^0.81.1", - "@deephaven/filters": "^0.81.0", - "@deephaven/golden-layout": "^0.81.1", - "@deephaven/grid": "^0.81.0", - "@deephaven/icons": "^0.81.0", - "@deephaven/iris-grid": "^0.81.1", - "@deephaven/jsapi-bootstrap": "^0.81.1", - "@deephaven/jsapi-components": "^0.81.1", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/dashboard-core-plugins/-/dashboard-core-plugins-0.84.0.tgz", + "integrity": "sha512-rhEO3M8f34fA0Dn5vex/lUwkgEqhkaOuAXmYjmKIK5TI220uxia930aaVaDBFw/vhacktNEH6KGNRR1ZWjugxg==", + "dependencies": { + "@deephaven/chart": "^0.84.0", + "@deephaven/components": "^0.84.0", + "@deephaven/console": "^0.84.0", + "@deephaven/dashboard": "^0.84.0", + "@deephaven/file-explorer": "^0.84.0", + "@deephaven/filters": "^0.84.0", + "@deephaven/golden-layout": "^0.84.0", + "@deephaven/grid": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/iris-grid": "^0.84.0", + "@deephaven/jsapi-bootstrap": "^0.84.0", + "@deephaven/jsapi-components": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/jsapi-utils": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/plugin": "^0.81.1", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/redux": "^0.81.1", - "@deephaven/storage": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@deephaven/jsapi-utils": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/plugin": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/redux": "^0.84.0", + "@deephaven/storage": "^0.84.0", + "@deephaven/utils": "^0.84.0", "@fortawesome/react-fontawesome": "^0.2.0", "classnames": "^2.3.1", "fast-deep-equal": "^3.1.3", @@ -32472,19 +32373,52 @@ "react-redux": "^7.2.4" } }, - "plugins/ui/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/@deephaven/jsapi-types": { - "version": "1.0.0-dev0.34.0", - "license": "Apache-2.0" + "plugins/ui/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/@deephaven/console": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/console/-/console-0.84.0.tgz", + "integrity": "sha512-S5QAkns4vt5e1r2T3VQ/c8YhOnXNi+blTk/n4rHE1VAhH6qphRp1pehF9TQzRG859cSXT3JH2CBoe9efi7WVbw==", + "dependencies": { + "@deephaven/chart": "^0.84.0", + "@deephaven/components": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/jsapi-bootstrap": "^0.84.0", + "@deephaven/jsapi-types": "1.0.0-dev0.34.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/storage": "^0.84.0", + "@deephaven/utils": "^0.84.0", + "@fortawesome/react-fontawesome": "^0.2.0", + "classnames": "^2.3.1", + "linkifyjs": "^4.1.0", + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1", + "memoize-one": "^5.1.1", + "memoizee": "^0.4.15", + "monaco-editor": "^0.41.0", + "nanoid": "^5.0.7", + "papaparse": "5.3.2", + "popper.js": "^1.16.1", + "prop-types": "^15.7.2", + "shell-quote": "^1.7.2" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } }, - "plugins/ui/src/js/node_modules/@deephaven/file-explorer": { - "version": "0.81.1", - "license": "Apache-2.0", + "plugins/ui/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/@deephaven/file-explorer": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/file-explorer/-/file-explorer-0.84.0.tgz", + "integrity": "sha512-AJ1kJZXhkRz+b2H26eolfr9eYkDxbWL1AsNjwu42Quv54/cncOu2WaDXkbOhVwlpLfae20f1P3X0JnTVFFP20w==", "dependencies": { - "@deephaven/components": "^0.81.1", - "@deephaven/icons": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/storage": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@deephaven/components": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/storage": "^0.84.0", + "@deephaven/utils": "^0.84.0", "@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/react-fontawesome": "^0.2.0", "classnames": "^2.3.1", @@ -32498,18 +32432,47 @@ "react": ">=16.8.0" } }, - "plugins/ui/src/js/node_modules/@deephaven/filters": { - "version": "0.81.0", - "license": "Apache-2.0", + "plugins/ui/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/@deephaven/golden-layout": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/golden-layout/-/golden-layout-0.84.0.tgz", + "integrity": "sha512-Pmy157rhKbf7U5YV6rBg7/r1ZHTHATw2UMQ501JEKAbOThrHIWrzktKk2Kfd4kpDs1CYPZsNJEuYwkzd+Xy2wA==", + "dependencies": { + "@deephaven/components": "^0.84.0", + "jquery": "^3.6.0", + "nanoid": "^5.0.7" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "plugins/ui/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/@deephaven/jsapi-types": { + "version": "1.0.0-dev0.34.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" + }, + "plugins/ui/src/js/node_modules/@deephaven/dashboard-core-plugins/node_modules/@deephaven/storage": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/storage/-/storage-0.84.0.tgz", + "integrity": "sha512-P/KJT2U04WypIxvx1Ws7l/02jUwIPdkonfUH9ezUK5YXzakwmMiXBvV2/jTBGrRpw/BfDZOkj25FlpDA4yib/A==", + "dependencies": { + "@deephaven/filters": "^0.84.0", + "@deephaven/log": "^0.84.0", + "lodash.throttle": "^4.1.1" + }, "engines": { "node": ">=16" + }, + "peerDependencies": { + "react": ">=16.8.0" } }, - "plugins/ui/src/js/node_modules/@deephaven/golden-layout": { - "version": "0.81.1", - "license": "Apache-2.0", + "plugins/ui/src/js/node_modules/@deephaven/dashboard/node_modules/@deephaven/golden-layout": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/golden-layout/-/golden-layout-0.84.0.tgz", + "integrity": "sha512-Pmy157rhKbf7U5YV6rBg7/r1ZHTHATw2UMQ501JEKAbOThrHIWrzktKk2Kfd4kpDs1CYPZsNJEuYwkzd+Xy2wA==", "dependencies": { - "@deephaven/components": "^0.81.1", + "@deephaven/components": "^0.84.0", "jquery": "^3.6.0", "nanoid": "^5.0.7" }, @@ -32518,11 +32481,20 @@ "react-dom": ">=16.8.0" } }, + "plugins/ui/src/js/node_modules/@deephaven/filters": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/filters/-/filters-0.84.0.tgz", + "integrity": "sha512-hu6DiGoFrMrJKP2sNFmBjHkMx6CKLDNTNlnt6WAdCbfw+tUZmc60seD0/l0Z5P/Z70TJUxqWyjUcWnE2KToMog==", + "engines": { + "node": ">=16" + } + }, "plugins/ui/src/js/node_modules/@deephaven/grid": { - "version": "0.81.0", - "license": "Apache-2.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/grid/-/grid-0.84.0.tgz", + "integrity": "sha512-IHCkad8zEO/M11ykLFhunDI40bKwJGadXf+NcsyTHdSkvATYlMe/EHaKZKXhzQtnoQmEv4kwkFSomiZ+oU4N0g==", "dependencies": { - "@deephaven/utils": "^0.81.0", + "@deephaven/utils": "^0.84.0", "classnames": "^2.3.1", "color-convert": "^2.0.1", "event-target-shim": "^6.0.2", @@ -32540,8 +32512,9 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/icons": { - "version": "0.81.0", - "license": "Apache-2.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/icons/-/icons-0.84.0.tgz", + "integrity": "sha512-aynGI8lBV0xLt4ivWAYIzULtyfJQwmgA/4npZruorSrS+x9ELrwAsZtPGqXAmZ0kDTLHenTKIBVOj1nSo9NvAg==", "dependencies": { "@fortawesome/fontawesome-common-types": "^6.1.1" }, @@ -32551,21 +32524,22 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/iris-grid": { - "version": "0.81.1", - "license": "Apache-2.0", - "dependencies": { - "@deephaven/components": "^0.81.1", - "@deephaven/console": "^0.81.1", - "@deephaven/filters": "^0.81.0", - "@deephaven/grid": "^0.81.0", - "@deephaven/icons": "^0.81.0", - "@deephaven/jsapi-components": "^0.81.1", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/iris-grid/-/iris-grid-0.84.0.tgz", + "integrity": "sha512-ilM9FxcsKeRIANgw5p5yN2cu5OtxRYHRLJ8dyF21ND9xjQ0e58hByqBnIclVuhakuaTl6qacxkCebjZgooxOIg==", + "dependencies": { + "@deephaven/components": "^0.84.0", + "@deephaven/console": "^0.84.0", + "@deephaven/filters": "^0.84.0", + "@deephaven/grid": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/jsapi-components": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/jsapi-utils": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/storage": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@deephaven/jsapi-utils": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/storage": "^0.84.0", + "@deephaven/utils": "^0.84.0", "@dnd-kit/core": "^6.1.0", "@dnd-kit/sortable": "^7.0.2", "@dnd-kit/utilities": "^3.2.2", @@ -32591,19 +32565,73 @@ "react-dom": ">=16.8.0" } }, + "plugins/ui/src/js/node_modules/@deephaven/iris-grid/node_modules/@deephaven/console": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/console/-/console-0.84.0.tgz", + "integrity": "sha512-S5QAkns4vt5e1r2T3VQ/c8YhOnXNi+blTk/n4rHE1VAhH6qphRp1pehF9TQzRG859cSXT3JH2CBoe9efi7WVbw==", + "dependencies": { + "@deephaven/chart": "^0.84.0", + "@deephaven/components": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/jsapi-bootstrap": "^0.84.0", + "@deephaven/jsapi-types": "1.0.0-dev0.34.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/storage": "^0.84.0", + "@deephaven/utils": "^0.84.0", + "@fortawesome/react-fontawesome": "^0.2.0", + "classnames": "^2.3.1", + "linkifyjs": "^4.1.0", + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1", + "memoize-one": "^5.1.1", + "memoizee": "^0.4.15", + "monaco-editor": "^0.41.0", + "nanoid": "^5.0.7", + "papaparse": "5.3.2", + "popper.js": "^1.16.1", + "prop-types": "^15.7.2", + "shell-quote": "^1.7.2" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "plugins/ui/src/js/node_modules/@deephaven/iris-grid/node_modules/@deephaven/jsapi-types": { "version": "1.0.0-dev0.34.0", - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" + }, + "plugins/ui/src/js/node_modules/@deephaven/iris-grid/node_modules/@deephaven/storage": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/storage/-/storage-0.84.0.tgz", + "integrity": "sha512-P/KJT2U04WypIxvx1Ws7l/02jUwIPdkonfUH9ezUK5YXzakwmMiXBvV2/jTBGrRpw/BfDZOkj25FlpDA4yib/A==", + "dependencies": { + "@deephaven/filters": "^0.84.0", + "@deephaven/log": "^0.84.0", + "lodash.throttle": "^4.1.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "react": ">=16.8.0" + } }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-bootstrap": { - "version": "0.81.1", - "license": "Apache-2.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-bootstrap/-/jsapi-bootstrap-0.84.0.tgz", + "integrity": "sha512-Aew3Lo+T9DRV1MLL89jeWORiMZ940gBQNz3kWbW7z/stcTQR89Wxynjt7tiaNRnBxBb0TgYrhphjlz01LAKjUw==", "dependencies": { - "@deephaven/components": "^0.81.1", + "@deephaven/components": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/utils": "^0.81.0" + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/utils": "^0.84.0" }, "engines": { "node": ">=16" @@ -32614,19 +32642,21 @@ }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-bootstrap/node_modules/@deephaven/jsapi-types": { "version": "1.0.0-dev0.34.0", - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-components": { - "version": "0.81.1", - "license": "Apache-2.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-components/-/jsapi-components-0.84.0.tgz", + "integrity": "sha512-suo2BSyBxNoR7KxS2DCX+FxCBdvaq3eFrrSjqLG3HmxOg3ps3qLdqoiLEpn6cVw0cZTqS0K2jGbkE9oyoDj+tA==", "dependencies": { - "@deephaven/components": "^0.81.1", - "@deephaven/jsapi-bootstrap": "^0.81.1", + "@deephaven/components": "^0.84.0", + "@deephaven/jsapi-bootstrap": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/jsapi-utils": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@deephaven/jsapi-utils": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/utils": "^0.84.0", "@types/js-cookie": "^3.0.3", "classnames": "^2.3.2", "js-cookie": "^3.0.5", @@ -32642,20 +32672,23 @@ }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-components/node_modules/@deephaven/jsapi-types": { "version": "1.0.0-dev0.34.0", - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-types": { - "version": "1.0.0-dev0.34.3", - "license": "Apache-2.0" + "version": "1.0.0-dev0.35.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.35.0.tgz", + "integrity": "sha512-X35g2ktmXbiTwjMNF20IkuNawJJ6Tlvrv23VuUVIjWHkpWcmyCYWIBle2zo7QAF6nnJpkccwFKJiC+TIkWl7hg==" }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-utils": { - "version": "0.81.0", - "license": "Apache-2.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-utils/-/jsapi-utils-0.84.0.tgz", + "integrity": "sha512-CwYs9NHPs3wb+D0PM4VTBrqXzaHNHmuHTkep8XitZHAr814jOGcQhnkTauSpo+ulPwnheweO8C8wMjjBH/VojQ==", "dependencies": { - "@deephaven/filters": "^0.81.0", + "@deephaven/filters": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/log": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@deephaven/log": "^0.84.0", + "@deephaven/utils": "^0.84.0", "lodash.clamp": "^4.0.3", "nanoid": "^5.0.7" }, @@ -32665,11 +32698,13 @@ }, "plugins/ui/src/js/node_modules/@deephaven/jsapi-utils/node_modules/@deephaven/jsapi-types": { "version": "1.0.0-dev0.34.0", - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" }, "plugins/ui/src/js/node_modules/@deephaven/log": { - "version": "0.81.0", - "license": "Apache-2.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/log/-/log-0.84.0.tgz", + "integrity": "sha512-B3KS2n/dT8GPblR8Top9GPB53pMmUglAMUVg93V3X10EPemE1jwiYEoJuceZ20JpRncCfRVuazrNYP7GItjWPQ==", "dependencies": { "event-target-shim": "^6.0.2" }, @@ -32678,16 +32713,17 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/plugin": { - "version": "0.81.1", - "license": "Apache-2.0", - "dependencies": { - "@deephaven/components": "^0.81.1", - "@deephaven/golden-layout": "^0.81.1", - "@deephaven/icons": "^0.81.0", - "@deephaven/iris-grid": "^0.81.1", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/plugin/-/plugin-0.84.0.tgz", + "integrity": "sha512-G3f3WGc159TVUZOekZPmUAChshdDqE7OzuigGXeFlv/CCmlQhX5t1BWwqfYRFXkHwV5zk9UUyuQEhrNAUS+Zmg==", + "dependencies": { + "@deephaven/components": "^0.84.0", + "@deephaven/golden-layout": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/iris-grid": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", "@fortawesome/fontawesome-common-types": "^6.1.1", "@fortawesome/react-fontawesome": "^0.2.0" }, @@ -32698,17 +32734,33 @@ "react": ">=16.8.0" } }, + "plugins/ui/src/js/node_modules/@deephaven/plugin/node_modules/@deephaven/golden-layout": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/golden-layout/-/golden-layout-0.84.0.tgz", + "integrity": "sha512-Pmy157rhKbf7U5YV6rBg7/r1ZHTHATw2UMQ501JEKAbOThrHIWrzktKk2Kfd4kpDs1CYPZsNJEuYwkzd+Xy2wA==", + "dependencies": { + "@deephaven/components": "^0.84.0", + "jquery": "^3.6.0", + "nanoid": "^5.0.7" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "plugins/ui/src/js/node_modules/@deephaven/plugin/node_modules/@deephaven/jsapi-types": { "version": "1.0.0-dev0.34.0", - "license": "Apache-2.0" + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" }, "plugins/ui/src/js/node_modules/@deephaven/react-hooks": { - "version": "0.81.0", - "license": "Apache-2.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/react-hooks/-/react-hooks-0.84.0.tgz", + "integrity": "sha512-VIcBAkfdyKI5JbITW5kouDfyfEm1ggUhbAYNWRUFlRSPNkoWxFfflc4eplQAfmj/VDjaVAizWNjc1JbH8OG/tg==", "dependencies": { - "@adobe/react-spectrum": "3.33.1", - "@deephaven/log": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@adobe/react-spectrum": "3.35.1", + "@deephaven/log": "^0.84.0", + "@deephaven/utils": "^0.84.0", "lodash.debounce": "^4.0.8", "lodash.throttle": "^4.1.1", "nanoid": "^5.0.7" @@ -32721,13 +32773,14 @@ } }, "plugins/ui/src/js/node_modules/@deephaven/redux": { - "version": "0.81.1", - "license": "Apache-2.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/redux/-/redux-0.84.0.tgz", + "integrity": "sha512-mj05IMOPtKhol5eLdiHORdyvnUv/bH7/sSV18q8hYJ3eHtpKyvuou3256s4NSpvgUCjyxTvQbknR9qemk1fVAw==", "dependencies": { "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/jsapi-utils": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/plugin": "^0.81.1", + "@deephaven/jsapi-utils": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/plugin": "^0.84.0", "fast-deep-equal": "^3.1.3", "proxy-memoize": "^3.0.0", "redux-thunk": "2.4.1" @@ -32741,26 +32794,13 @@ }, "plugins/ui/src/js/node_modules/@deephaven/redux/node_modules/@deephaven/jsapi-types": { "version": "1.0.0-dev0.34.0", - "license": "Apache-2.0" - }, - "plugins/ui/src/js/node_modules/@deephaven/storage": { - "version": "0.81.0", - "license": "Apache-2.0", - "dependencies": { - "@deephaven/filters": "^0.81.0", - "@deephaven/log": "^0.81.0", - "lodash.throttle": "^4.1.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "react": ">=16.8.0" - } + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" }, "plugins/ui/src/js/node_modules/@deephaven/utils": { - "version": "0.81.0", - "license": "Apache-2.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/utils/-/utils-0.84.0.tgz", + "integrity": "sha512-eWTlmxtdYFuV7q127AwMyLnf5j0FGpPG6gJ+2ChpFeMS+ZfOHpgcRHZC2+j3y/b5z4mGm2bIjzQDJpMNPL4thg==", "engines": { "node": ">=16" } @@ -32789,7 +32829,8 @@ }, "plugins/ui/src/js/node_modules/color-convert": { "version": "2.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dependencies": { "color-name": "~1.1.4" }, @@ -32799,7 +32840,8 @@ }, "plugins/ui/src/js/node_modules/color-name": { "version": "1.1.4", - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "plugins/ui/src/js/node_modules/event-target-shim": { "version": "6.0.2", @@ -32829,7 +32871,8 @@ }, "plugins/ui/src/js/node_modules/redux-thunk": { "version": "2.4.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", + "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", "peerDependencies": { "redux": "^4" } @@ -36250,21 +36293,21 @@ "@deephaven/js-plugin-ui": { "version": "file:plugins/ui/src/js", "requires": { - "@deephaven/chart": "^0.81.1", - "@deephaven/components": "^0.81.1", - "@deephaven/dashboard": "^0.81.1", - "@deephaven/dashboard-core-plugins": "^0.81.1", - "@deephaven/grid": "^0.81.0", - "@deephaven/icons": "^0.81.0", - "@deephaven/iris-grid": "^0.81.1", - "@deephaven/jsapi-bootstrap": "^0.81.1", - "@deephaven/jsapi-components": "^0.81.1", - "@deephaven/jsapi-types": "^1.0.0-dev0.34.3", - "@deephaven/log": "^0.81.0", - "@deephaven/plugin": "^0.81.1", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/redux": "^0.81.1", - "@deephaven/utils": "^0.81.0", + "@deephaven/chart": "^0.84.0", + "@deephaven/components": "^0.84.0", + "@deephaven/dashboard": "^0.84.0", + "@deephaven/dashboard-core-plugins": "^0.84.0", + "@deephaven/grid": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/iris-grid": "^0.84.0", + "@deephaven/jsapi-bootstrap": "^0.84.0", + "@deephaven/jsapi-components": "^0.84.0", + "@deephaven/jsapi-types": "^1.0.0-dev0.35.0", + "@deephaven/log": "^0.84.0", + "@deephaven/plugin": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/redux": "^0.84.0", + "@deephaven/utils": "^0.84.0", "@fortawesome/react-fontawesome": "^0.2.0", "@react-types/shared": "^3.22.0", "@types/react": "^17.0.2", @@ -36279,77 +36322,18 @@ "vite": "~4.1.4" }, "dependencies": { - "@adobe/react-spectrum": { - "version": "3.33.1", - "requires": { - "@internationalized/string": "^3.2.0", - "@react-aria/i18n": "^3.10.0", - "@react-aria/ssr": "^3.9.1", - "@react-aria/utils": "^3.23.0", - "@react-aria/visually-hidden": "^3.8.8", - "@react-spectrum/actionbar": "^3.4.1", - "@react-spectrum/actiongroup": "^3.10.1", - "@react-spectrum/avatar": "^3.0.8", - "@react-spectrum/badge": "^3.1.9", - "@react-spectrum/breadcrumbs": "^3.9.3", - "@react-spectrum/button": "^3.16.0", - "@react-spectrum/buttongroup": "^3.6.9", - "@react-spectrum/calendar": "^3.4.5", - "@react-spectrum/checkbox": "^3.9.2", - "@react-spectrum/combobox": "^3.12.1", - "@react-spectrum/contextualhelp": "^3.6.7", - "@react-spectrum/datepicker": "^3.9.2", - "@react-spectrum/dialog": "^3.8.7", - "@react-spectrum/divider": "^3.5.9", - "@react-spectrum/dnd": "^3.3.6", - "@react-spectrum/form": "^3.7.2", - "@react-spectrum/icon": "^3.7.9", - "@react-spectrum/illustratedmessage": "^3.4.9", - "@react-spectrum/image": "^3.4.9", - "@react-spectrum/inlinealert": "^3.2.1", - "@react-spectrum/labeledvalue": "^3.1.10", - "@react-spectrum/layout": "^3.6.1", - "@react-spectrum/link": "^3.6.3", - "@react-spectrum/list": "^3.7.6", - "@react-spectrum/listbox": "^3.12.5", - "@react-spectrum/menu": "^3.17.0", - "@react-spectrum/meter": "^3.4.9", - "@react-spectrum/numberfield": "^3.8.2", - "@react-spectrum/overlays": "^5.5.3", - "@react-spectrum/picker": "^3.14.1", - "@react-spectrum/progress": "^3.7.3", - "@react-spectrum/provider": "^3.9.3", - "@react-spectrum/radio": "^3.7.2", - "@react-spectrum/searchfield": "^3.8.2", - "@react-spectrum/slider": "^3.6.5", - "@react-spectrum/statuslight": "^3.5.9", - "@react-spectrum/switch": "^3.5.1", - "@react-spectrum/table": "^3.12.6", - "@react-spectrum/tabs": "^3.8.6", - "@react-spectrum/tag": "^3.2.2", - "@react-spectrum/text": "^3.5.1", - "@react-spectrum/textfield": "^3.11.2", - "@react-spectrum/theme-dark": "^3.5.7", - "@react-spectrum/theme-default": "^3.5.7", - "@react-spectrum/theme-light": "^3.4.7", - "@react-spectrum/tooltip": "^3.6.3", - "@react-spectrum/view": "^3.6.6", - "@react-spectrum/well": "^3.4.9", - "@react-stately/collections": "^3.10.4", - "@react-stately/data": "^3.11.0", - "@react-types/shared": "^3.22.0" - } - }, "@deephaven/chart": { - "version": "0.81.1", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/chart/-/chart-0.84.0.tgz", + "integrity": "sha512-UUtwO27zr8m213ZTmmO/Xv9XL28phSIb/OLBSpKtbW4iL+rXdzFf3t42q7kGfukXf4MUG2i+CyG/GKiKe+3vZw==", "requires": { - "@deephaven/components": "^0.81.1", - "@deephaven/icons": "^0.81.0", + "@deephaven/components": "^0.84.0", + "@deephaven/icons": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/jsapi-utils": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@deephaven/jsapi-utils": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/utils": "^0.84.0", "buffer": "^6.0.3", "fast-deep-equal": "^3.1.3", "lodash.debounce": "^4.0.8", @@ -36367,13 +36351,15 @@ } }, "@deephaven/components": { - "version": "0.81.1", - "requires": { - "@adobe/react-spectrum": "3.33.1", - "@deephaven/icons": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/components/-/components-0.84.0.tgz", + "integrity": "sha512-3lUz+JGQQMxdG9MmQbReHfWr4h0FiIOJtH17DIQnelYP+VDoiqWFfg4c/uEs7EMRIQAtKi8NI88DrXzoEwhS7w==", + "requires": { + "@adobe/react-spectrum": "3.35.1", + "@deephaven/icons": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/utils": "^0.84.0", "@fortawesome/fontawesome-svg-core": "^6.2.1", "@fortawesome/react-fontawesome": "^0.2.0", "@react-spectrum/theme-default": "^3.5.1", @@ -36397,77 +36383,61 @@ "react-window": "^1.8.6" } }, - "@deephaven/console": { - "version": "0.81.1", - "requires": { - "@deephaven/chart": "^0.81.1", - "@deephaven/components": "^0.81.1", - "@deephaven/icons": "^0.81.0", - "@deephaven/jsapi-bootstrap": "^0.81.1", - "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/storage": "^0.81.0", - "@deephaven/utils": "^0.81.0", - "@fortawesome/react-fontawesome": "^0.2.0", - "classnames": "^2.3.1", - "linkifyjs": "^4.1.0", - "lodash.debounce": "^4.0.8", - "lodash.throttle": "^4.1.1", - "memoize-one": "^5.1.1", - "memoizee": "^0.4.15", - "monaco-editor": "^0.41.0", - "nanoid": "^5.0.7", - "papaparse": "5.3.2", - "popper.js": "^1.16.1", - "prop-types": "^15.7.2", - "shell-quote": "^1.7.2" - }, - "dependencies": { - "@deephaven/jsapi-types": { - "version": "1.0.0-dev0.34.0" - } - } - }, "@deephaven/dashboard": { - "version": "0.81.1", - "requires": { - "@deephaven/components": "^0.81.1", - "@deephaven/golden-layout": "^0.81.1", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/redux": "^0.81.1", - "@deephaven/utils": "^0.81.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/dashboard/-/dashboard-0.84.0.tgz", + "integrity": "sha512-AsYI6ppk0OtB3p/S+VVMuWO/RJJ/V3XcLQsBy5oA1GG+2sD6AMjtFG5QbTGQopI995UPEcUWnLODWr3CcPItQg==", + "requires": { + "@deephaven/components": "^0.84.0", + "@deephaven/golden-layout": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/redux": "^0.84.0", + "@deephaven/utils": "^0.84.0", "fast-deep-equal": "^3.1.3", "lodash.ismatch": "^4.1.1", "lodash.throttle": "^4.1.1", "nanoid": "^5.0.7", "prop-types": "^15.7.2" + }, + "dependencies": { + "@deephaven/golden-layout": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/golden-layout/-/golden-layout-0.84.0.tgz", + "integrity": "sha512-Pmy157rhKbf7U5YV6rBg7/r1ZHTHATw2UMQ501JEKAbOThrHIWrzktKk2Kfd4kpDs1CYPZsNJEuYwkzd+Xy2wA==", + "requires": { + "@deephaven/components": "^0.84.0", + "jquery": "^3.6.0", + "nanoid": "^5.0.7" + } + } } }, "@deephaven/dashboard-core-plugins": { - "version": "0.81.1", - "requires": { - "@deephaven/chart": "^0.81.1", - "@deephaven/components": "^0.81.1", - "@deephaven/console": "^0.81.1", - "@deephaven/dashboard": "^0.81.1", - "@deephaven/file-explorer": "^0.81.1", - "@deephaven/filters": "^0.81.0", - "@deephaven/golden-layout": "^0.81.1", - "@deephaven/grid": "^0.81.0", - "@deephaven/icons": "^0.81.0", - "@deephaven/iris-grid": "^0.81.1", - "@deephaven/jsapi-bootstrap": "^0.81.1", - "@deephaven/jsapi-components": "^0.81.1", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/dashboard-core-plugins/-/dashboard-core-plugins-0.84.0.tgz", + "integrity": "sha512-rhEO3M8f34fA0Dn5vex/lUwkgEqhkaOuAXmYjmKIK5TI220uxia930aaVaDBFw/vhacktNEH6KGNRR1ZWjugxg==", + "requires": { + "@deephaven/chart": "^0.84.0", + "@deephaven/components": "^0.84.0", + "@deephaven/console": "^0.84.0", + "@deephaven/dashboard": "^0.84.0", + "@deephaven/file-explorer": "^0.84.0", + "@deephaven/filters": "^0.84.0", + "@deephaven/golden-layout": "^0.84.0", + "@deephaven/grid": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/iris-grid": "^0.84.0", + "@deephaven/jsapi-bootstrap": "^0.84.0", + "@deephaven/jsapi-components": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/jsapi-utils": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/plugin": "^0.81.1", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/redux": "^0.81.1", - "@deephaven/storage": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@deephaven/jsapi-utils": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/plugin": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/redux": "^0.84.0", + "@deephaven/storage": "^0.84.0", + "@deephaven/utils": "^0.84.0", "@fortawesome/react-fontawesome": "^0.2.0", "classnames": "^2.3.1", "fast-deep-equal": "^3.1.3", @@ -36486,41 +36456,90 @@ "remark-math": "^5.1.1" }, "dependencies": { + "@deephaven/console": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/console/-/console-0.84.0.tgz", + "integrity": "sha512-S5QAkns4vt5e1r2T3VQ/c8YhOnXNi+blTk/n4rHE1VAhH6qphRp1pehF9TQzRG859cSXT3JH2CBoe9efi7WVbw==", + "requires": { + "@deephaven/chart": "^0.84.0", + "@deephaven/components": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/jsapi-bootstrap": "^0.84.0", + "@deephaven/jsapi-types": "1.0.0-dev0.34.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/storage": "^0.84.0", + "@deephaven/utils": "^0.84.0", + "@fortawesome/react-fontawesome": "^0.2.0", + "classnames": "^2.3.1", + "linkifyjs": "^4.1.0", + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1", + "memoize-one": "^5.1.1", + "memoizee": "^0.4.15", + "monaco-editor": "^0.41.0", + "nanoid": "^5.0.7", + "papaparse": "5.3.2", + "popper.js": "^1.16.1", + "prop-types": "^15.7.2", + "shell-quote": "^1.7.2" + } + }, + "@deephaven/file-explorer": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/file-explorer/-/file-explorer-0.84.0.tgz", + "integrity": "sha512-AJ1kJZXhkRz+b2H26eolfr9eYkDxbWL1AsNjwu42Quv54/cncOu2WaDXkbOhVwlpLfae20f1P3X0JnTVFFP20w==", + "requires": { + "@deephaven/components": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/storage": "^0.84.0", + "@deephaven/utils": "^0.84.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" + } + }, + "@deephaven/golden-layout": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/golden-layout/-/golden-layout-0.84.0.tgz", + "integrity": "sha512-Pmy157rhKbf7U5YV6rBg7/r1ZHTHATw2UMQ501JEKAbOThrHIWrzktKk2Kfd4kpDs1CYPZsNJEuYwkzd+Xy2wA==", + "requires": { + "@deephaven/components": "^0.84.0", + "jquery": "^3.6.0", + "nanoid": "^5.0.7" + } + }, "@deephaven/jsapi-types": { - "version": "1.0.0-dev0.34.0" + "version": "1.0.0-dev0.34.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" + }, + "@deephaven/storage": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/storage/-/storage-0.84.0.tgz", + "integrity": "sha512-P/KJT2U04WypIxvx1Ws7l/02jUwIPdkonfUH9ezUK5YXzakwmMiXBvV2/jTBGrRpw/BfDZOkj25FlpDA4yib/A==", + "requires": { + "@deephaven/filters": "^0.84.0", + "@deephaven/log": "^0.84.0", + "lodash.throttle": "^4.1.1" + } } } }, - "@deephaven/file-explorer": { - "version": "0.81.1", - "requires": { - "@deephaven/components": "^0.81.1", - "@deephaven/icons": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/storage": "^0.81.0", - "@deephaven/utils": "^0.81.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" - } - }, "@deephaven/filters": { - "version": "0.81.0" - }, - "@deephaven/golden-layout": { - "version": "0.81.1", - "requires": { - "@deephaven/components": "^0.81.1", - "jquery": "^3.6.0", - "nanoid": "^5.0.7" - } + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/filters/-/filters-0.84.0.tgz", + "integrity": "sha512-hu6DiGoFrMrJKP2sNFmBjHkMx6CKLDNTNlnt6WAdCbfw+tUZmc60seD0/l0Z5P/Z70TJUxqWyjUcWnE2KToMog==" }, "@deephaven/grid": { - "version": "0.81.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/grid/-/grid-0.84.0.tgz", + "integrity": "sha512-IHCkad8zEO/M11ykLFhunDI40bKwJGadXf+NcsyTHdSkvATYlMe/EHaKZKXhzQtnoQmEv4kwkFSomiZ+oU4N0g==", "requires": { - "@deephaven/utils": "^0.81.0", + "@deephaven/utils": "^0.84.0", "classnames": "^2.3.1", "color-convert": "^2.0.1", "event-target-shim": "^6.0.2", @@ -36532,26 +36551,30 @@ } }, "@deephaven/icons": { - "version": "0.81.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/icons/-/icons-0.84.0.tgz", + "integrity": "sha512-aynGI8lBV0xLt4ivWAYIzULtyfJQwmgA/4npZruorSrS+x9ELrwAsZtPGqXAmZ0kDTLHenTKIBVOj1nSo9NvAg==", "requires": { "@fortawesome/fontawesome-common-types": "^6.1.1" } }, "@deephaven/iris-grid": { - "version": "0.81.1", - "requires": { - "@deephaven/components": "^0.81.1", - "@deephaven/console": "^0.81.1", - "@deephaven/filters": "^0.81.0", - "@deephaven/grid": "^0.81.0", - "@deephaven/icons": "^0.81.0", - "@deephaven/jsapi-components": "^0.81.1", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/iris-grid/-/iris-grid-0.84.0.tgz", + "integrity": "sha512-ilM9FxcsKeRIANgw5p5yN2cu5OtxRYHRLJ8dyF21ND9xjQ0e58hByqBnIclVuhakuaTl6qacxkCebjZgooxOIg==", + "requires": { + "@deephaven/components": "^0.84.0", + "@deephaven/console": "^0.84.0", + "@deephaven/filters": "^0.84.0", + "@deephaven/grid": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/jsapi-components": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/jsapi-utils": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/storage": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@deephaven/jsapi-utils": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/storage": "^0.84.0", + "@deephaven/utils": "^0.84.0", "@dnd-kit/core": "^6.1.0", "@dnd-kit/sortable": "^7.0.2", "@dnd-kit/utilities": "^3.2.2", @@ -36570,36 +36593,83 @@ "react-transition-group": "^4.4.2" }, "dependencies": { + "@deephaven/console": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/console/-/console-0.84.0.tgz", + "integrity": "sha512-S5QAkns4vt5e1r2T3VQ/c8YhOnXNi+blTk/n4rHE1VAhH6qphRp1pehF9TQzRG859cSXT3JH2CBoe9efi7WVbw==", + "requires": { + "@deephaven/chart": "^0.84.0", + "@deephaven/components": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/jsapi-bootstrap": "^0.84.0", + "@deephaven/jsapi-types": "1.0.0-dev0.34.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/storage": "^0.84.0", + "@deephaven/utils": "^0.84.0", + "@fortawesome/react-fontawesome": "^0.2.0", + "classnames": "^2.3.1", + "linkifyjs": "^4.1.0", + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1", + "memoize-one": "^5.1.1", + "memoizee": "^0.4.15", + "monaco-editor": "^0.41.0", + "nanoid": "^5.0.7", + "papaparse": "5.3.2", + "popper.js": "^1.16.1", + "prop-types": "^15.7.2", + "shell-quote": "^1.7.2" + } + }, "@deephaven/jsapi-types": { - "version": "1.0.0-dev0.34.0" + "version": "1.0.0-dev0.34.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" + }, + "@deephaven/storage": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/storage/-/storage-0.84.0.tgz", + "integrity": "sha512-P/KJT2U04WypIxvx1Ws7l/02jUwIPdkonfUH9ezUK5YXzakwmMiXBvV2/jTBGrRpw/BfDZOkj25FlpDA4yib/A==", + "requires": { + "@deephaven/filters": "^0.84.0", + "@deephaven/log": "^0.84.0", + "lodash.throttle": "^4.1.1" + } } } }, "@deephaven/jsapi-bootstrap": { - "version": "0.81.1", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-bootstrap/-/jsapi-bootstrap-0.84.0.tgz", + "integrity": "sha512-Aew3Lo+T9DRV1MLL89jeWORiMZ940gBQNz3kWbW7z/stcTQR89Wxynjt7tiaNRnBxBb0TgYrhphjlz01LAKjUw==", "requires": { - "@deephaven/components": "^0.81.1", + "@deephaven/components": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/utils": "^0.81.0" + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/utils": "^0.84.0" }, "dependencies": { "@deephaven/jsapi-types": { - "version": "1.0.0-dev0.34.0" + "version": "1.0.0-dev0.34.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" } } }, "@deephaven/jsapi-components": { - "version": "0.81.1", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-components/-/jsapi-components-0.84.0.tgz", + "integrity": "sha512-suo2BSyBxNoR7KxS2DCX+FxCBdvaq3eFrrSjqLG3HmxOg3ps3qLdqoiLEpn6cVw0cZTqS0K2jGbkE9oyoDj+tA==", "requires": { - "@deephaven/components": "^0.81.1", - "@deephaven/jsapi-bootstrap": "^0.81.1", + "@deephaven/components": "^0.84.0", + "@deephaven/jsapi-bootstrap": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/jsapi-utils": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@deephaven/jsapi-utils": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/utils": "^0.84.0", "@types/js-cookie": "^3.0.3", "classnames": "^2.3.2", "js-cookie": "^3.0.5", @@ -36608,92 +36678,116 @@ }, "dependencies": { "@deephaven/jsapi-types": { - "version": "1.0.0-dev0.34.0" + "version": "1.0.0-dev0.34.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" } } }, "@deephaven/jsapi-types": { - "version": "1.0.0-dev0.34.3" + "version": "1.0.0-dev0.35.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.35.0.tgz", + "integrity": "sha512-X35g2ktmXbiTwjMNF20IkuNawJJ6Tlvrv23VuUVIjWHkpWcmyCYWIBle2zo7QAF6nnJpkccwFKJiC+TIkWl7hg==" }, "@deephaven/jsapi-utils": { - "version": "0.81.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-utils/-/jsapi-utils-0.84.0.tgz", + "integrity": "sha512-CwYs9NHPs3wb+D0PM4VTBrqXzaHNHmuHTkep8XitZHAr814jOGcQhnkTauSpo+ulPwnheweO8C8wMjjBH/VojQ==", "requires": { - "@deephaven/filters": "^0.81.0", + "@deephaven/filters": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/log": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@deephaven/log": "^0.84.0", + "@deephaven/utils": "^0.84.0", "lodash.clamp": "^4.0.3", "nanoid": "^5.0.7" }, "dependencies": { "@deephaven/jsapi-types": { - "version": "1.0.0-dev0.34.0" + "version": "1.0.0-dev0.34.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" } } }, "@deephaven/log": { - "version": "0.81.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/log/-/log-0.84.0.tgz", + "integrity": "sha512-B3KS2n/dT8GPblR8Top9GPB53pMmUglAMUVg93V3X10EPemE1jwiYEoJuceZ20JpRncCfRVuazrNYP7GItjWPQ==", "requires": { "event-target-shim": "^6.0.2" } }, "@deephaven/plugin": { - "version": "0.81.1", - "requires": { - "@deephaven/components": "^0.81.1", - "@deephaven/golden-layout": "^0.81.1", - "@deephaven/icons": "^0.81.0", - "@deephaven/iris-grid": "^0.81.1", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/plugin/-/plugin-0.84.0.tgz", + "integrity": "sha512-G3f3WGc159TVUZOekZPmUAChshdDqE7OzuigGXeFlv/CCmlQhX5t1BWwqfYRFXkHwV5zk9UUyuQEhrNAUS+Zmg==", + "requires": { + "@deephaven/components": "^0.84.0", + "@deephaven/golden-layout": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/iris-grid": "^0.84.0", "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/log": "^0.81.0", - "@deephaven/react-hooks": "^0.81.0", + "@deephaven/log": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", "@fortawesome/fontawesome-common-types": "^6.1.1", "@fortawesome/react-fontawesome": "^0.2.0" }, "dependencies": { + "@deephaven/golden-layout": { + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/golden-layout/-/golden-layout-0.84.0.tgz", + "integrity": "sha512-Pmy157rhKbf7U5YV6rBg7/r1ZHTHATw2UMQ501JEKAbOThrHIWrzktKk2Kfd4kpDs1CYPZsNJEuYwkzd+Xy2wA==", + "requires": { + "@deephaven/components": "^0.84.0", + "jquery": "^3.6.0", + "nanoid": "^5.0.7" + } + }, "@deephaven/jsapi-types": { - "version": "1.0.0-dev0.34.0" + "version": "1.0.0-dev0.34.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" } } }, "@deephaven/react-hooks": { - "version": "0.81.0", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/react-hooks/-/react-hooks-0.84.0.tgz", + "integrity": "sha512-VIcBAkfdyKI5JbITW5kouDfyfEm1ggUhbAYNWRUFlRSPNkoWxFfflc4eplQAfmj/VDjaVAizWNjc1JbH8OG/tg==", "requires": { - "@adobe/react-spectrum": "3.33.1", - "@deephaven/log": "^0.81.0", - "@deephaven/utils": "^0.81.0", + "@adobe/react-spectrum": "3.35.1", + "@deephaven/log": "^0.84.0", + "@deephaven/utils": "^0.84.0", "lodash.debounce": "^4.0.8", "lodash.throttle": "^4.1.1", "nanoid": "^5.0.7" } }, "@deephaven/redux": { - "version": "0.81.1", + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/redux/-/redux-0.84.0.tgz", + "integrity": "sha512-mj05IMOPtKhol5eLdiHORdyvnUv/bH7/sSV18q8hYJ3eHtpKyvuou3256s4NSpvgUCjyxTvQbknR9qemk1fVAw==", "requires": { "@deephaven/jsapi-types": "1.0.0-dev0.34.0", - "@deephaven/jsapi-utils": "^0.81.0", - "@deephaven/log": "^0.81.0", - "@deephaven/plugin": "^0.81.1", + "@deephaven/jsapi-utils": "^0.84.0", + "@deephaven/log": "^0.84.0", + "@deephaven/plugin": "^0.84.0", "fast-deep-equal": "^3.1.3", "proxy-memoize": "^3.0.0", "redux-thunk": "2.4.1" }, "dependencies": { "@deephaven/jsapi-types": { - "version": "1.0.0-dev0.34.0" + "version": "1.0.0-dev0.34.0", + "resolved": "https://registry.npmjs.org/@deephaven/jsapi-types/-/jsapi-types-1.0.0-dev0.34.0.tgz", + "integrity": "sha512-UiIbmCaMx5mPOGCWdgOCfZtccMhh55jv3qzeN3qBp3YUi46uGfWY5kfCU3hWRtaQvUgO7n0XhBKTd4K/pxv9ng==" } } }, - "@deephaven/storage": { - "version": "0.81.0", - "requires": { - "@deephaven/filters": "^0.81.0", - "@deephaven/log": "^0.81.0", - "lodash.throttle": "^4.1.1" - } - }, "@deephaven/utils": { - "version": "0.81.0" + "version": "0.84.0", + "resolved": "https://registry.npmjs.org/@deephaven/utils/-/utils-0.84.0.tgz", + "integrity": "sha512-eWTlmxtdYFuV7q127AwMyLnf5j0FGpPG6gJ+2ChpFeMS+ZfOHpgcRHZC2+j3y/b5z4mGm2bIjzQDJpMNPL4thg==" }, "buffer": { "version": "6.0.3", @@ -36704,12 +36798,16 @@ }, "color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "requires": { "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.4" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "event-target-shim": { "version": "6.0.2" @@ -36719,6 +36817,8 @@ }, "redux-thunk": { "version": "2.4.1", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", + "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", "requires": {} }, "typescript": { @@ -51521,7 +51621,9 @@ "dev": true }, "proxy-compare": { - "version": "3.0.0" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-3.0.0.tgz", + "integrity": "sha512-y44MCkgtZUCT9tZGuE278fB7PWVf7fRYy0vbRXAts2o5F0EfC4fIQrvQQGBJo1WJbFcVLXzApOscyJuZqHQc1w==" }, "proxy-from-env": { "version": "1.1.0", @@ -51529,6 +51631,8 @@ }, "proxy-memoize": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proxy-memoize/-/proxy-memoize-3.0.0.tgz", + "integrity": "sha512-2fs4eIg4w6SfOjKHGVdg5tJ9WgHifEXKo2gfS/+tHGajO2YtAu03lLs+ltNKnteGKvq3SvHromkZeKus4J39/g==", "requires": { "proxy-compare": "^3.0.0" } diff --git a/plugins/ui/DESIGN.md b/plugins/ui/DESIGN.md index e720cc6a7..7b11ae401 100644 --- a/plugins/ui/DESIGN.md +++ b/plugins/ui/DESIGN.md @@ -1011,7 +1011,6 @@ def my_dashboard(): d = my_dashboard() ``` - ##### ui.tabs A tabs component can be used to organize content in a collection of tabs, allowing users to navigating between the different tabs. Children (the tabs) can be specified in one of two ways: @@ -1021,13 +1020,13 @@ A tabs component can be used to organize content in a collection of tabs, allowi ###### Parameters -| Parameter | Type | Description | -| ----------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `*children` | `Item \| TabList \| TabPanels` | The tab panels to render within the tabs component. | -| `on_change` | `Callable[[Key], None] \| None` | Alias of `on_selection_change`. Handler that is called when the tab selection changes. | -| `**props` | `Any` | Any other [Tabs](https://react-spectrum.adobe.com/react-spectrum/Tabs.html#tabs-props) prop -| +| Parameter | Type | Description | +| ----------- | ------------------------------- | ------------------------------------------------------------------------------------------- | +| `*children` | `Item \| TabList \| TabPanels` | The tab panels to render within the tabs component. | +| `on_change` | `Callable[[Key], None] \| None` | Alias of `on_selection_change`. Handler that is called when the tab selection changes. | +| `**props` | `Any` | Any other [Tabs](https://react-spectrum.adobe.com/react-spectrum/Tabs.html#tabs-props) prop | +| ###### Tabs using `ui.tab` @@ -1074,7 +1073,7 @@ ui.tabs( ###### Tabs using `ui.tab_list` and `ui.tab_panels` -If you need more control over the layout, types, and styling of the tabs, you can specify tabs using `ui.tab_list` and `ui.tab_panels` with `ui.tabs`. This approach provides greater flexibility for complex or customized tab structures, compared to the concise method of passing `ui.tab` to `ui.tabs`. +If you need more control over the layout, types, and styling of the tabs, you can specify tabs using `ui.tab_list` and `ui.tab_panels` with `ui.tabs`. This approach provides greater flexibility for complex or customized tab structures, compared to the concise method of passing `ui.tab` to `ui.tabs`. With this method, the keys must be provided and match for the tabs declared in the `ui.tab_list` and `ui.tab_panels`. @@ -1138,7 +1137,6 @@ t4 = ui.tabs( ) ``` - #### Components ##### ui.list_action_group @@ -1189,7 +1187,6 @@ def list_action_menu( | `on_open_change` | `Callable[[bool, Key], None] \| None` | The first argument is a boolean indicating if the menu is open, the second argument is the key of the list_view item. | | `**props` | `Any` | Any other [ActionMenu](https://react-spectrum.adobe.com/react-spectrum/ActionMenu.html) prop. | - ##### ui.list_view A list view that can be used to create a list of items. Children should be one of three types: @@ -1309,8 +1306,6 @@ list_view5 = ui.list_view( ``` - - ###### ui.date_picker A date picker that can be used to select a date. @@ -1750,6 +1745,7 @@ picker7 = ui.picker( on_selection_change=set_color ) ``` + ##### ui.section A section that can be added to a menu, such as a `ui.picker`. Children are the dropdown options. @@ -1790,7 +1786,6 @@ ui.item( | `*children` | `Stringable` | The options to render within the item. | | `**props` | `Any` | Any other Item prop | - ##### ui.item_table_source An item table source wraps a Table or PartitionedTable to provide additional information for @@ -1824,7 +1819,6 @@ ui.item_table_source( | `title_column` | `ColumnName \| None` | Only valid if table is of type `PartitionedTable`. The column of values to display as section names. Should be the same for all values in the constituent `Table`. If not specified, the section titles will be created from the `key_columns` of the `PartitionedTable`. | | `actions` | `ListActionGroupElement \| ListActionMenuElement \| None` | The action group or menus to render for all elements within the component, if supported. | - #### ui.table `ui.table` is a wrapper for a Deephaven `Table` object that allows you to add UI customizations or callbacks. The basic syntax for creating a `UITable` is: @@ -1887,40 +1881,44 @@ ui_table( on_quick_filter: Callable[[ColumnName, QuickFilterExpression], None] | None on_freeze_column: Callable[[ColumnName], None] | None, on_hide_column: Callable[[ColumnName], None] | None, - on_sort: Callable[[ColumnName, LiteralSortDirection], None] | None + on_sort: Callable[[ColumnName, LiteralSortDirection], None] | None, + context_menu: ResolvableContextMenuItem | list[ResolvableContextMenuItem] | None, + context_header_menu: ResolvableContextMenuItem | list[ResolvableContextMenuItem] | None, ) -> UITable ``` -| Parameter | Type | Description | -| ------------------------ | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `always_fetch_columns` | `ColumnNameCombination \| None` | The columns to always fetch from the server. May be a single column name. These will not be affected by the users current viewport/horizontal scrolling. Useful if you have a column with key value data that you want to always include in the data sent for row click operations. | -| `back_columns` | `ColumnNameCombination \| None` | The columns to show at the back of the table. May be a single column name. These will not be moveable in the UI. | -| `freeze_columns` | `ColumnNameCombination \| None` | The columns to freeze to the front of the table. May be a single column name. These will always be visible and not affected by horizontal scrolling. | -| `front_columns` | `ColumnNameCombination \| None` | The columns to show at the front of the table. May be a single column name. These will not be moveable in the UI. | -| `hide_columns` | `ColumnNameCombination \| None` | The columns to hide by default from the table. May be a single column name. The user can still resize the columns to view them. | -| `quick_filters` | `dict[ColumnName, QuickFilterExpression] \| None` | Quick filters for the UI to apply to the table. | -| `show_search` | `bool` | `True` to show the search bar by default, `False` to not. `False` by default. | -| `show_quick_filters` | `bool` | `True` to show the quick filters by default, `False` to not. `False` by default. | -| `show_column_headers` | `bool \| None` | `True` to show the column headers by default, `False` to not. | -| `selection_mode` | `SelectionMode \| None` | Can be `MULTIPLE` to allow multiple selection or `SINGLE` to not allow it. | -| `selection_area` | `SelectionArea \| None` | The unit that is selected on press. Can be `ROW`, `COLUMN`, or `CELL`. | -| `selection_style` | `SelectionStyleCombination \| None` | The style of the selection. Can be `HIGHLIGHT`, `CHECKBOX`, or a combination of those. | -| `selected_rows` | `RowIndexCombination \| None` | The rows that are selected by default. Only valid if `selection_area` is `ROW`. | -| `selected_columns` | `ColumnIndexCombination \| None` | The columns that are selected by default. Only valid if `selection_area` is `COLUMN`. | -| `selected_cells` | `CellIndexCombination \| None` | The cells that are selected by default. Only valid if `selection_area` is `CELL`. | -| `density` | `DensityMode \| None` | The density of the table. Can be `COMPACT`, `REGULAR`, or `SPACIOUS`. | -| `column_display_names` | `dict[ColumnName, ColumnNameCombination] \| None` | The display names. If a sequence of column names is provided for a column, the display name will be set to the longest column name that can be fully displayed. | -| `on_row_press` | `Callable[[RowIndex, RowData], None] \| None` | The callback function to run when a cell in a row is released (such as a click). The first parameter is the row index, and the second is the row data provided in a dictionary where the column names are the keys. | -| `on_row_double_press` | `Callable[[RowIndex, RowData], None] \| None` | The callback function to run when a cell in a row is double pressed. The first parameter is the row index, and the second is the row data provided in a dictionary where the column names are the keys. | -| `on_cell_press` | `Callable[[CellIndex, CellData], None] \| None` | The callback function to run when a cell is released (such as a click). The first parameter is the cell index, and the second is the cell data. | -| `on_cell_double_press` | `Callable[[CellIndex, CellData], None] \| None` | The callback function to run when a cell is double pressed. The first parameter is the cell index, and the second is the cell data. | -| `on_column_press` | `Callable[[ColumnName], None] \| None` | The callback function to run when a column is released (such as a click). The only parameter is the column name. | -| `on_column_double_press` | `Callable[[ColumnName], None] \| None` | The callback function to run when a cell in a column is double pressed. The only parameter is the column name. | -| `on_search` | `Callable[[str], None] \| None` | The callback function to run when the search bar is used. The only parameter is the search string. | -| `on_quick_filter` | `Callable[[ColumnName, QuickFilterExpression], None] \| None` | The callback function to run when a quick filter is applied. The first parameter is the column name, and the second is the quick filter expression. | -| `on_freeze_column` | `Callable[[ColumnName], None] \| None` | The callback function to run when a column is frozen. The only parameter is the frozen column name. | -| `on_hide_column` | `Callable[[ColumnName], None] \| None` | The callback function to run when a column is hidden. The only parameter is the hidden column name. | -| `on_sort` | `Callable[[ColumnName, LiteralSortDirection], None] \| None` | The callback function to run when a column is sorted. The first parameter is the column name, and the second is the sort direction. | +| Parameter | Type | Description | +| ------------------------ | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `always_fetch_columns` | `ColumnNameCombination \| None` | The columns to always fetch from the server. May be a single column name. These will not be affected by the users current viewport/horizontal scrolling. Useful if you have a column with key value data that you want to always include in the data sent for row click operations. | +| `back_columns` | `ColumnNameCombination \| None` | The columns to show at the back of the table. May be a single column name. These will not be moveable in the UI. | +| `freeze_columns` | `ColumnNameCombination \| None` | The columns to freeze to the front of the table. May be a single column name. These will always be visible and not affected by horizontal scrolling. | +| `front_columns` | `ColumnNameCombination \| None` | The columns to show at the front of the table. May be a single column name. These will not be moveable in the UI. | +| `hide_columns` | `ColumnNameCombination \| None` | The columns to hide by default from the table. May be a single column name. The user can still resize the columns to view them. | +| `quick_filters` | `dict[ColumnName, QuickFilterExpression] \| None` | Quick filters for the UI to apply to the table. | +| `show_search` | `bool` | `True` to show the search bar by default, `False` to not. `False` by default. | +| `show_quick_filters` | `bool` | `True` to show the quick filters by default, `False` to not. `False` by default. | +| `show_column_headers` | `bool \| None` | `True` to show the column headers by default, `False` to not. | +| `selection_mode` | `SelectionMode \| None` | Can be `MULTIPLE` to allow multiple selection or `SINGLE` to not allow it. | +| `selection_area` | `SelectionArea \| None` | The unit that is selected on press. Can be `ROW`, `COLUMN`, or `CELL`. | +| `selection_style` | `SelectionStyleCombination \| None` | The style of the selection. Can be `HIGHLIGHT`, `CHECKBOX`, or a combination of those. | +| `selected_rows` | `RowIndexCombination \| None` | The rows that are selected by default. Only valid if `selection_area` is `ROW`. | +| `selected_columns` | `ColumnIndexCombination \| None` | The columns that are selected by default. Only valid if `selection_area` is `COLUMN`. | +| `selected_cells` | `CellIndexCombination \| None` | The cells that are selected by default. Only valid if `selection_area` is `CELL`. | +| `density` | `DensityMode \| None` | The density of the table. Can be `COMPACT`, `REGULAR`, or `SPACIOUS`. | +| `column_display_names` | `dict[ColumnName, ColumnNameCombination] \| None` | The display names. If a sequence of column names is provided for a column, the display name will be set to the longest column name that can be fully displayed. | +| `on_row_press` | `Callable[[RowIndex, RowData], None] \| None` | The callback function to run when a cell in a row is released (such as a click). The first parameter is the row index, and the second is the row data provided in a dictionary where the column names are the keys. | +| `on_row_double_press` | `Callable[[RowIndex, RowData], None] \| None` | The callback function to run when a cell in a row is double pressed. The first parameter is the row index, and the second is the row data provided in a dictionary where the column names are the keys. | +| `on_cell_press` | `Callable[[CellIndex, CellData], None] \| None` | The callback function to run when a cell is released (such as a click). The first parameter is the cell index, and the second is the cell data. | +| `on_cell_double_press` | `Callable[[CellIndex, CellData], None] \| None` | The callback function to run when a cell is double pressed. The first parameter is the cell index, and the second is the cell data. | +| `on_column_press` | `Callable[[ColumnName], None] \| None` | The callback function to run when a column is released (such as a click). The only parameter is the column name. | +| `on_column_double_press` | `Callable[[ColumnName], None] \| None` | The callback function to run when a cell in a column is double pressed. The only parameter is the column name. | +| `on_search` | `Callable[[str], None] \| None` | The callback function to run when the search bar is used. The only parameter is the search string. | +| `on_quick_filter` | `Callable[[ColumnName, QuickFilterExpression], None] \| None` | The callback function to run when a quick filter is applied. The first parameter is the column name, and the second is the quick filter expression. | +| `on_freeze_column` | `Callable[[ColumnName], None] \| None` | The callback function to run when a column is frozen. The only parameter is the frozen column name. | +| `on_hide_column` | `Callable[[ColumnName], None] \| None` | The callback function to run when a column is hidden. The only parameter is the hidden column name. | +| `on_sort` | `Callable[[ColumnName, LiteralSortDirection], None] \| None` | The callback function to run when a column is sorted. The first parameter is the column name, and the second is the sort direction. | +| `context_menu` | `ResolvableContextMenuItem \| list[ResolvableContextMenuItem] \| None` | The context menu items to show when right-clicking on a cell in the table. Can contain `ContextMenuSubmenuItem`s to define submenus. | +| `context_header_menu` | `ResolvableContextMenuItem \| list[ResolvableContextMenuItem] \| None` | The context menu items to show when right-clicking on the column header (i.e. column name). Can contain `ContextMenuSubmenuItem`s to define submenus. | `ui.table` will also support the below methods. @@ -2027,28 +2025,6 @@ ui_table.color_row( | `color` | `Color \| None` | The text color. Accepts hex color strings or Deephaven color names. | | `background_color` | `Color \| None` | The background color. Accepts hex color strings or Deephaven color names. | -##### context_menu - -Add custom items to the context menu. You can provide a list of actions that always appear, or a callback that can process the selection and send back menu items asynchronously. You can also specify whether you want the menu items provided for a cell context menu, a header context menu, or some combination of those. You can also chain multiple sets of menu items by calling `.context_menu` multiple times. - -###### Syntax - -```py -ui_table.context_menu( - items: ContextMenuAction - | list[ContextMenuAction] - | Callable[[CellIndex, RowData], ContextMenuAction | list[ContextMenuAction]], - mode: ContextMenuMode = "CELL", -) -> UITable -``` - -###### Parameters - -| Parameter | Type | Description | -| --------- | ------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `items` | `ContextMenuAction \| list[ContextMenuAction] \| Callable[[CellIndex, RowData], ContextMenuAction \| list[ContextMenuAction]]` | The items to add to the context menu. May be a single `ContextMenuAction`, a list of `ContextMenuAction` objects, or a callback function that takes the cell index and row data and returns either a single `ContextMenuAction` or a list of `ContextMenuAction` objects. | -| `mode` | `ContextMenuMode` | Which specific context menu(s) to add the menu item(s) to. Can be one or more modes. Using `None` will add menu items in all cases.
- `CELL`: Triggered from a cell.
- `ROW_HEADER`: Triggered from a row header.
- `COLUMN_HEADER`: Triggered from a column header. | - ##### data_bar Applies data bar formatting to the specified column. @@ -2315,7 +2291,6 @@ ColumnName = str ColumnData = list[Any] # ID of a component. Used for linking. ComponentId = str -ContextMenuAction = dict[str, Any] ContextMenuModeOption = Literal["CELL", "ROW_HEADER", "COLUMN_HEADER"] ContextMenuMode = ContextMenuModeOption | list[ContextMenuModeOption] | None DataBarAxis = Literal["PROPORTIONAL", "MIDDLE", "DIRECTIONAL"] @@ -2406,6 +2381,106 @@ class LinkPoint(TypedDict): # Column to link to column: str + + +class ContextMenuActionParams(TypedDict): + """ + Parameters given to a context menu action + """ + + value: Any + """ + Value of the cell. + """ + + text_value: str + """ + Rendered text for the cell. + """ + + column_name: str + """ + Name of the column. + """ + + is_column_header: bool + """ + Whether the context menu was opened on a column header. + """ + + is_row_header: bool + """ + Whether the context menu was opened on a row header. + """ + + +ContextMenuAction = Callable[[ContextMenuActionParams], None] +""" +The action to execute when the context menu item is clicked. +""" + + +class ContextMenuItemBase(TypedDict): + """ + Base props that context menu items and submenu items share. + """ + + title: str + """ + Title to display for the action. + """ + + icon: NotRequired[str] + """ + The name of the icon to display next to the action. + The name must be a valid name for ui.icon. + """ + + description: NotRequired[str] + """ + Description for the action. Will be used as a tooltip for the action. + """ + + +class ContextMenuActionItem(ContextMenuItemBase): + """ + An item that appears in a context menu and performs an action when clicked. + """ + + action: ContextMenuAction + """ + Action to run when the menu item is clicked. + """ + + +class ContextMenuSubmenuItem(ContextMenuItemBase): + """ + An item that contains a submenu for a context menu. + """ + + actions: list["ResolvableContextMenuItem"] + """ + A list of actions that will form the submenu for the item. + """ + + +ContextMenuItem = ContextMenuActionItem | ContextMenuSubmenuItem +""" +An item that can appear in a context menu. +May contain an action item or a submenu item. +""" + +ResolvableContextMenuItem = ( + ContextMenuItem + | Callable[ + [ContextMenuActionParams], ContextMenuItem | List[ContextMenuItem] | None + ] +) +""" +A context menu item or a function that returns a list of context menu items or None. +This can be used to dynamically generate context menu items based on the cell the menu is opened on. +""" + ``` #### Context diff --git a/plugins/ui/docs/README.md b/plugins/ui/docs/README.md index c8d245d4d..856938da3 100644 --- a/plugins/ui/docs/README.md +++ b/plugins/ui/docs/README.md @@ -204,6 +204,7 @@ my_checkbox = ui_checkbox() ![Checkbox](_assets/checkbox.png) ## ActionGroup (string values) + An ActionGroup is a grouping of ActionButtons that are related to one another. ```python @@ -227,6 +228,7 @@ my_action_group = ui_action_group() ``` ## ActionMenu (string values) + ActionMenu combines an ActionButton with a Menu for simple "more actions" use cases. ```python @@ -356,6 +358,7 @@ def ui_picker_table(): pick_table = ui_picker_table() ``` + ![Use a picker to select from a table](_assets/pick_table.png) ## Picker (item table source) @@ -402,6 +405,7 @@ pick_table_source = ui_picker_table_source() ![Use a picker to select from a table source](_assets/pick_table_source.png) ## ListView (string values) + A list view that can be used to create a list of selectable items. Here's a basic example for selecting from a list of string values and displaying the selected key in a text field. ```python @@ -487,6 +491,7 @@ def ui_list_view_table(): lv_table = ui_list_view_table() ``` + ![Use a list view to select from a table](_assets/lv_table.png) ## ListView (item table source) @@ -594,6 +599,7 @@ my_list_view_action_group = ui_list_view_action_group() ``` ## ListView (list action menu) + A list view can take a `list_action_menu` as its `actions` prop. ```python @@ -1283,6 +1289,72 @@ te = ui.table( ![Table events](table_events.png) +### ui.table Context Menu + +Items can be added to the bottom of the `ui.table` context menu (right-click menu) by using the `context_menu` or `context_header_menu` props. The `context_menu` prop adds items to the cell context menu, while the `context_header_menu` prop adds items to the column header context menu. + +Menu items must have a `title` and either an `action` or `actions` prop. They may have an `icon` which is the name of the icon that will be passed to `ui.icon`. + +The `action` prop is a callback that is called when the item is clicked and receives info about the cell that was clicked when the menu was opened. + +The `actions` prop is an array of menu items that will be displayed in a sub-menu. Sub-menus can contain other sub-menus for a nested menu. + +Menu items can be dynamically created by instead passing a function as the context item. The function will be called with the data of the cell that was clicked when the menu was opened, and must return the menu items or None. + +```py +from deephaven import ui +import deephaven.plot.express as dx + +t = ui.table( + dx.data.stocks(), + context_menu=[ + { + "title": "Context item", + "icon": "dhTruck", + "action": lambda d: print("Context item", d) + }, + { + "title": "Nested menu", + "actions": [ + { + "title": "Nested item 1", + "action": lambda d: print("Nested item 1", d) + } + { + "title": "Nested item 2", + "icon": "vsCheck" + "action": lambda d: print("Nested item 2", d) + } + ] + } + ], + context_header_menu={ + "title": "Header context menu item", + "action": lambda d: print("Header context menu item", d) + } +) +``` + +The following example shows creating context menu items dynamically so that the item only appears on the `sym` column. If multiple functions are passed in a list, each will be called and any items they return will be added to the context menu. + +```py +from deephaven import ui +import deephaven.plot.express as dx + +def create_context_menu(data): + if data["column_name"] == "sym": + return { + "title": f"Print {data['value']}", + "action": lambda d: print(d['value']) + } + return None + +t = ui.table( + dx.data.stocks(), + context_menu=create_context_menu +) +``` + ## Re-using components In a previous example, we created a text_filter_table component. We can re-use that component, and display two tables with an input filter side-by-side: diff --git a/plugins/ui/src/deephaven/ui/components/table.py b/plugins/ui/src/deephaven/ui/components/table.py index 4b120b2ca..f0dc911c9 100644 --- a/plugins/ui/src/deephaven/ui/components/table.py +++ b/plugins/ui/src/deephaven/ui/components/table.py @@ -8,6 +8,7 @@ ColumnPressCallback, QuickFilterExpression, RowPressCallback, + ResolvableContextMenuItem, ) @@ -23,6 +24,12 @@ def table( quick_filters: dict[ColumnName, QuickFilterExpression] | None = None, show_quick_filters: bool = False, show_search: bool = False, + context_menu: ( + ResolvableContextMenuItem | list[ResolvableContextMenuItem] | None + ) = None, + context_header_menu: ( + ResolvableContextMenuItem | list[ResolvableContextMenuItem] | None + ) = None, ) -> UITable: """ Customization to how a table is displayed, how it behaves, and listen to UI events. @@ -48,6 +55,12 @@ def table( quick_filters: The quick filters to apply to the table. Dictionary of column name to filter value. show_quick_filters: Whether to show the quick filter bar by default. show_search: Whether to show the search bar by default. + context_menu: The context menu items to show when a cell is right clicked. + May contain action items or submenu items. + May also be a function that receives the cell data and returns the context menu items or None. + context_header_menu: The context menu items to show when a column header is right clicked. + May contain action items or submenu items. + May also be a function that receives the column header data and returns the context menu items or None. """ props = locals() del props["table"] diff --git a/plugins/ui/src/deephaven/ui/elements/UITable.py b/plugins/ui/src/deephaven/ui/elements/UITable.py index 4e8fa1324..77680f052 100644 --- a/plugins/ui/src/deephaven/ui/elements/UITable.py +++ b/plugins/ui/src/deephaven/ui/elements/UITable.py @@ -18,12 +18,8 @@ AggregationOperation, QuickFilterExpression, Color, - ContextMenuAction, - CellIndex, CellPressCallback, ColumnPressCallback, - RowData, - ContextMenuMode, DataBarAxis, DataBarValuePlacement, DataBarDirection, @@ -307,42 +303,6 @@ def color_row( """ raise NotImplementedError() - def context_menu( - self, - items: ( - ContextMenuAction - | list[ContextMenuAction] - | Callable[ - [CellIndex, RowData], ContextMenuAction | list[ContextMenuAction] - ] - ), - mode: ContextMenuMode = "CELL", - ) -> "UITable": - """ - Add custom items to the context menu. - You can provide a list of actions that always appear, - or a callback that can process the selection and send back menu items asynchronously. - You can also specify whether you want the menu items provided for a cell context menu, - a header context menu, or some combination of those. - You can also chain multiple sets of menu items by calling `.context_menu` multiple times. - - Args: - items: The items to add to the context menu. - May be a single `ContextMenuAction`, a list of `ContextMenuAction` objects, - or a callback function that takes the cell index and row data and returns either a single - `ContextMenuAction` or a list of `ContextMenuAction` objects. - mode: Which specific context menu(s) to add the menu item(s) to. - Can be one or more modes. - Using `None` will add menu items in all cases. - `CELL`: Triggered from a cell. - `ROW_HEADER`: Triggered from a row header. - `COLUMN_HEADER`: Triggered from a column header. - - Returns: - A new UITable - """ - raise NotImplementedError() - def data_bar( self, col: str, diff --git a/plugins/ui/src/deephaven/ui/types/types.py b/plugins/ui/src/deephaven/ui/types/types.py index a69f6e021..d6c09967e 100644 --- a/plugins/ui/src/deephaven/ui/types/types.py +++ b/plugins/ui/src/deephaven/ui/types/types.py @@ -1,6 +1,4 @@ -import datetime -import pandas -import numpy +import sys from typing import ( Any, Dict, @@ -10,9 +8,18 @@ List, Tuple, Callable, - TypedDict, Sequence, ) + +if sys.version_info < (3, 11): + from typing_extensions import TypedDict, NotRequired +else: + from typing import TypedDict, NotRequired + +import datetime +import pandas +import numpy + from deephaven import SortDirection from deephaven.dtypes import DType @@ -54,6 +61,105 @@ class RowDataValue(CellData): """ +class ContextMenuActionParams(TypedDict): + """ + Parameters given to a context menu action + """ + + value: Any + """ + Value of the cell. + """ + + text_value: str + """ + Rendered text for the cell. + """ + + column_name: str + """ + Name of the column. + """ + + is_column_header: bool + """ + Whether the context menu was opened on a column header. + """ + + is_row_header: bool + """ + Whether the context menu was opened on a row header. + """ + + +ContextMenuAction = Callable[[ContextMenuActionParams], None] +""" +The action to execute when the context menu item is clicked. +""" + + +class ContextMenuItemBase(TypedDict): + """ + Base props that context menu items and submenu items share. + """ + + title: str + """ + Title to display for the action. + """ + + icon: NotRequired[str] + """ + The name of the icon to display next to the action. + The name must be a valid name for ui.icon. + """ + + description: NotRequired[str] + """ + Description for the action. Will be used as a tooltip for the action. + """ + + +class ContextMenuActionItem(ContextMenuItemBase): + """ + An item that appears in a context menu and performs an action when clicked. + """ + + action: ContextMenuAction + """ + Action to run when the menu item is clicked. + """ + + +class ContextMenuSubmenuItem(ContextMenuItemBase): + """ + An item that contains a submenu for a context menu. + """ + + actions: List["ResolvableContextMenuItem"] + """ + A list of actions that will form the submenu for the item. + """ + + +ContextMenuItem = Union[ContextMenuActionItem, ContextMenuSubmenuItem] +""" +An item that can appear in a context menu. +May contain an action item or a submenu item. +""" + +ResolvableContextMenuItem = Union[ + ContextMenuItem, + Callable[ + [ContextMenuActionParams], Union[ContextMenuItem, List[ContextMenuItem], None] + ], +] +""" +A context menu item or a function that returns a list of context menu items or None. +This can be used to dynamically generate context menu items based on the cell the menu is opened on. +""" + + class SliderChange(TypedDict): """ Data for a range slider change event. @@ -118,7 +224,6 @@ class SliderChange(TypedDict): DeephavenColor = Literal["salmon", "lemonchiffon"] HexColor = str Color = Union[DeephavenColor, HexColor] -ContextMenuAction = Dict[str, Any] ContextMenuModeOption = Literal["CELL", "ROW_HEADER", "COLUMN_HEADER"] ContextMenuMode = Union[ContextMenuModeOption, List[ContextMenuModeOption], None] DataBarAxis = Literal["PROPORTIONAL", "MIDDLE", "DIRECTIONAL"] diff --git a/plugins/ui/src/js/package.json b/plugins/ui/src/js/package.json index 77e68facb..71affb24f 100644 --- a/plugins/ui/src/js/package.json +++ b/plugins/ui/src/js/package.json @@ -41,21 +41,21 @@ "react-dom": "^17.0.2" }, "dependencies": { - "@deephaven/chart": "^0.81.1", - "@deephaven/components": "^0.81.1", - "@deephaven/dashboard": "^0.81.1", - "@deephaven/dashboard-core-plugins": "^0.81.1", - "@deephaven/grid": "^0.81.0", - "@deephaven/icons": "^0.81.0", - "@deephaven/iris-grid": "^0.81.1", - "@deephaven/jsapi-bootstrap": "^0.81.1", - "@deephaven/jsapi-components": "^0.81.1", - "@deephaven/jsapi-types": "^1.0.0-dev0.34.3", - "@deephaven/log": "^0.81.0", - "@deephaven/plugin": "^0.81.1", - "@deephaven/react-hooks": "^0.81.0", - "@deephaven/redux": "^0.81.1", - "@deephaven/utils": "^0.81.0", + "@deephaven/chart": "^0.84.0", + "@deephaven/components": "^0.84.0", + "@deephaven/dashboard": "^0.84.0", + "@deephaven/dashboard-core-plugins": "^0.84.0", + "@deephaven/grid": "^0.84.0", + "@deephaven/icons": "^0.84.0", + "@deephaven/iris-grid": "^0.84.0", + "@deephaven/jsapi-bootstrap": "^0.84.0", + "@deephaven/jsapi-components": "^0.84.0", + "@deephaven/jsapi-types": "^1.0.0-dev0.35.0", + "@deephaven/log": "^0.84.0", + "@deephaven/plugin": "^0.84.0", + "@deephaven/react-hooks": "^0.84.0", + "@deephaven/redux": "^0.84.0", + "@deephaven/utils": "^0.84.0", "@fortawesome/react-fontawesome": "^0.2.0", "@react-types/shared": "^3.22.0", "classnames": "^2.5.1", diff --git a/plugins/ui/src/js/src/elements/UITable.tsx b/plugins/ui/src/js/src/elements/UITable.tsx index 53e2b008d..89f0e397a 100644 --- a/plugins/ui/src/js/src/elements/UITable.tsx +++ b/plugins/ui/src/js/src/elements/UITable.tsx @@ -1,8 +1,10 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useSelector } from 'react-redux'; import { DehydratedQuickFilter, IrisGrid, + IrisGridType, + type IrisGridContextMenuData, IrisGridModel, IrisGridModelFactory, IrisGridProps, @@ -12,9 +14,10 @@ import { useApi } from '@deephaven/jsapi-bootstrap'; import type { dh } from '@deephaven/jsapi-types'; import Log from '@deephaven/log'; import { getSettings, RootState } from '@deephaven/redux'; -import { EMPTY_ARRAY } from '@deephaven/utils'; -import { UITableProps } from './utils/UITableUtils'; +import { GridMouseHandler } from '@deephaven/grid'; +import { UITableProps, wrapContextActions } from './utils/UITableUtils'; import UITableMouseHandler from './utils/UITableMouseHandler'; +import UITableContextMenuHandler from './utils/UITableContextMenuHandler'; const log = Log.module('@deephaven/js-plugin-ui/UITable'); @@ -31,8 +34,11 @@ export function UITable({ table: exportedTable, showSearch: showSearchBar, showQuickFilters, + contextMenu, + contextHeaderMenu, }: UITableProps): JSX.Element | null { const dh = useApi(); + const [irisGrid, setIrisGrid] = useState(null); const [model, setModel] = useState(); const [columns, setColumns] = useState(); const utils = useMemo(() => new IrisGridUtils(dh), [dh]); @@ -91,8 +97,8 @@ export function UITable({ const mouseHandlers = useMemo( () => - model - ? [ + model && irisGrid + ? ([ new UITableMouseHandler( model, onCellPress, @@ -102,19 +108,36 @@ export function UITable({ onRowPress, onRowDoublePress ), - ] - : EMPTY_ARRAY, + new UITableContextMenuHandler( + dh, + irisGrid, + model, + contextMenu, + contextHeaderMenu + ), + ] as readonly GridMouseHandler[]) + : undefined, [ model, + dh, + irisGrid, onCellPress, onCellDoublePress, onColumnPress, onColumnDoublePress, onRowPress, onRowDoublePress, + contextMenu, + contextHeaderMenu, ] ); + const onContextMenu = useCallback( + (data: IrisGridContextMenuData) => + wrapContextActions(contextMenu ?? [], data), + [contextMenu] + ); + const irisGridProps = useMemo( () => ({ @@ -125,6 +148,7 @@ export function UITable({ quickFilters: hydratedQuickFilters, isFilterBarShown: showQuickFilters, settings, + onContextMenu, }) satisfies Partial, [ mouseHandlers, @@ -134,6 +158,7 @@ export function UITable({ hydratedSorts, hydratedQuickFilters, settings, + onContextMenu, ] ); @@ -142,8 +167,12 @@ export function UITable({ return model ? (
- {/* eslint-disable-next-line react/jsx-props-no-spreading */} - + setIrisGrid(ref)} + model={model} + // eslint-disable-next-line react/jsx-props-no-spreading + {...irisGridProps} + />
) : null; } diff --git a/plugins/ui/src/js/src/elements/utils/UITableContextMenuHandler.ts b/plugins/ui/src/js/src/elements/utils/UITableContextMenuHandler.ts new file mode 100644 index 000000000..e0698e5d4 --- /dev/null +++ b/plugins/ui/src/js/src/elements/utils/UITableContextMenuHandler.ts @@ -0,0 +1,68 @@ +import { GridPoint, ModelIndex } from '@deephaven/grid'; +import type { ResolvableContextAction } from '@deephaven/components'; +import { + IrisGridModel, + IrisGridType, + IrisGridContextMenuHandler, +} from '@deephaven/iris-grid'; +import type { dh as DhType } from '@deephaven/jsapi-types'; +import { UITableProps, wrapContextActions } from './UITableUtils'; + +/** + * Context menu handler for UITable. + */ +class UITableContextMenuHandler extends IrisGridContextMenuHandler { + private model: IrisGridModel; + + private contextMenuItems: UITableProps['contextMenu']; + + private contextColumnHeaderItems: UITableProps['contextHeaderMenu']; + + constructor( + dh: typeof DhType, + irisGrid: IrisGridType, + model: IrisGridModel, + contextMenuItems: UITableProps['contextMenu'], + contextColumnHeaderItems: UITableProps['contextHeaderMenu'] + ) { + super(irisGrid, dh); + this.order -= 1; // Make it just above the default handler priority + this.irisGrid = irisGrid; + this.model = model; + this.contextMenuItems = contextMenuItems; + this.contextColumnHeaderItems = contextColumnHeaderItems; + } + + getHeaderActions( + modelIndex: ModelIndex, + gridPoint: GridPoint + ): ResolvableContextAction[] { + const { irisGrid, contextColumnHeaderItems, model } = this; + + const { column: columnIndex } = gridPoint; + const modelColumn = irisGrid.getModelColumn(columnIndex); + + if (!contextColumnHeaderItems || modelColumn == null) { + return super.getHeaderActions(modelIndex, gridPoint); + } + + const { columns } = model; + + const sourceCell = model.sourceForCell(modelColumn, 0); + const { column: sourceColumn } = sourceCell; + const column = columns[sourceColumn]; + + return [ + ...super.getHeaderActions(modelIndex, gridPoint), + ...wrapContextActions(contextColumnHeaderItems, { + value: null, + valueText: null, + rowIndex: null, + columnIndex: sourceColumn, + column, + }), + ]; + } +} + +export default UITableContextMenuHandler; diff --git a/plugins/ui/src/js/src/elements/utils/UITableUtils.tsx b/plugins/ui/src/js/src/elements/utils/UITableUtils.tsx index 1abb6aa1c..45a18095b 100644 --- a/plugins/ui/src/js/src/elements/utils/UITableUtils.tsx +++ b/plugins/ui/src/js/src/elements/utils/UITableUtils.tsx @@ -1,7 +1,23 @@ import type { dh } from '@deephaven/jsapi-types'; -import { ColumnName, DehydratedSort, RowIndex } from '@deephaven/iris-grid'; +import type { + ColumnName, + DehydratedSort, + IrisGridContextMenuData, + RowIndex, +} from '@deephaven/iris-grid'; +import type { + ContextAction, + ResolvableContextAction, +} from '@deephaven/components'; +import { ensureArray } from '@deephaven/utils'; import { ELEMENT_KEY, ElementNode, isElementNode } from './ElementUtils'; -import { ELEMENT_NAME, ElementName } from '../model/ElementConstants'; +import { getIcon } from './IconElementUtils'; +import { + ELEMENT_NAME, + ELEMENT_PREFIX, + ElementName, + ElementPrefix, +} from '../model/ElementConstants'; export type CellData = { type: string; @@ -18,6 +34,26 @@ export type ColumnIndex = number; export type RowDataMap = Record; +export interface UIContextItemParams { + value: unknown; + text_value: string | null; + column_name: string; + is_column_header: boolean; + is_row_header: boolean; +} + +export type UIContextItem = Omit & { + action?: (params: UIContextItemParams) => void; + + actions?: ResolvableUIContextItem[]; +}; + +type ResolvableUIContextItem = + | UIContextItem + | (( + params: UIContextItemParams + ) => Promise); + export interface UITableProps { table: dh.WidgetExportedObject; onCellPress?: (cellIndex: [ColumnIndex, RowIndex], data: CellData) => void; @@ -34,6 +70,8 @@ export interface UITableProps { sorts?: DehydratedSort[]; showSearch: boolean; showQuickFilters: boolean; + contextMenu?: ResolvableUIContextItem | ResolvableUIContextItem[]; + contextHeaderMenu?: ResolvableUIContextItem | ResolvableUIContextItem[]; [key: string]: unknown; } @@ -47,3 +85,64 @@ export function isUITable(obj: unknown): obj is UITableNode { (obj as UITableNode)[ELEMENT_KEY] === ELEMENT_NAME.uiTable ); } + +function wrapUIContextItem( + item: UIContextItem, + data: Omit +): ContextAction { + return { + group: 999999, // Default to the end of the menu + ...item, + icon: item.icon + ? getIcon(`${ELEMENT_PREFIX.icon}${item.icon}` as ElementPrefix['icon']) + : undefined, + action: item.action + ? () => { + item.action?.({ + value: data.value, + text_value: data.valueText, + column_name: data.column.name, + is_column_header: data.rowIndex == null, + is_row_header: data.columnIndex == null, + }); + } + : undefined, + actions: item.actions ? wrapContextActions(item.actions, data) : undefined, + } satisfies ContextAction; +} + +function wrapUIContextItems( + items: UIContextItem | UIContextItem[], + data: Omit +): ContextAction[] { + return ensureArray(items).map(item => wrapUIContextItem(item, data)); +} + +/** + * Wraps context item actions from the server so they are called with the cell info. + * @param items The context items from the server + * @param data The context menu data to use for the context items + * @returns Context items with the UI actions wrapped so they receive the cell info + */ +export function wrapContextActions( + items: ResolvableUIContextItem | ResolvableUIContextItem[], + data: Omit +): ResolvableContextAction[] { + return ensureArray(items).map(item => { + if (typeof item === 'function') { + return async () => + wrapUIContextItems( + (await item({ + value: data.value, + text_value: data.valueText, + column_name: data.column.name, + is_column_header: data.rowIndex == null, + is_row_header: data.columnIndex == null, + })) ?? [], + data + ); + } + + return wrapUIContextItem(item, data); + }); +} diff --git a/plugins/ui/src/ui.schema.json b/plugins/ui/src/ui.schema.json index 82cccb99b..e4fa98d86 100644 --- a/plugins/ui/src/ui.schema.json +++ b/plugins/ui/src/ui.schema.json @@ -60,6 +60,16 @@ "type": "array", "prefixItems": [{ "type": "object" }], "items": false + }, + "callCallableParams": { + "type": "array", + "prefixItems": [{ "type": "string" }, { "type": "array" }], + "items": false + }, + "closeCallableParams": { + "type": "array", + "prefixItems": [{ "type": "string" }], + "items": false } }, "type": "object", @@ -67,8 +77,15 @@ "jsonrpc": "2.0", "method": { "anyOf": [ - { "enum": ["documentUpdated", "documentError"] }, - { "pattern": "^cb_(0-9)+_(0-9)+$" } + { + "enum": [ + "documentUpdated", + "documentError", + "setState", + "callCallable", + "closeCallable" + ] + } ] }, "allOf": [ @@ -111,15 +128,24 @@ { "if": { "properties": { - "method": { "pattern": "^cb_(0-9)+_(0-9)+$" } + "method": { "pattern": "callCallable" } } }, "then": { "properties": { - "params": { - "type": "array", - "items": { "type": "any" } - } + "params": { "$ref": "#/defs/callCallableParams" } + } + } + }, + { + "if": { + "properties": { + "method": { "pattern": "closeCallable" } + } + }, + "then": { + "properties": { + "params": { "$ref": "#/defs/closeCallableParams" } } } }