diff --git a/package-lock.json b/package-lock.json index e71796cbf..e262da413 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,7 +21,6 @@ "@types/jest": "^29.2.5", "@types/node": "^20.11.17", "@types/prop-types": "^15.7.10", - "@types/shortid": "^0.0.29", "eslint": "^8.37.0", "identity-obj-proxy": "^3.0.0", "jest": "^29.6.2", @@ -11643,11 +11642,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/shortid": { - "version": "0.0.29", - "dev": true, - "license": "MIT" - }, "node_modules/@types/stack-utils": { "version": "2.0.3", "dev": true, @@ -23897,20 +23891,20 @@ "license": "ISC" }, "node_modules/nanoid": { - "version": "3.3.7", - "dev": true, + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==", "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "bin": { - "nanoid": "bin/nanoid.cjs" + "nanoid": "bin/nanoid.js" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": "^18 || >=20" } }, "node_modules/native-promise-only": { @@ -26064,6 +26058,24 @@ "license": "MIT", "peer": true }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/potpack": { "version": "1.0.2", "license": "ISC" @@ -26252,7 +26264,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 +26274,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" } @@ -30358,8 +30372,8 @@ "@deephaven/dashboard": "^0.40.0", "@deephaven/jsapi-types": "^0.40.0", "@deephaven/log": "^0.40.0", - "react-json-view": "^1.21.3", - "shortid": "^2.2.16" + "nanoid": "^5.0.7", + "react-json-view": "^1.21.3" }, "devDependencies": { "@types/react": "^17.0.2", @@ -31232,8 +31246,7 @@ "@deephaven/jsapi-bootstrap": "^0.58.0", "@deephaven/jsapi-types": "^0.58.0", "@deephaven/log": "^0.58.0", - "@deephaven/plugin": "^0.58.0", - "shortid": "^2.2.16" + "@deephaven/plugin": "^0.58.0" }, "devDependencies": { "@types/react": "^17.0.2", @@ -31621,11 +31634,11 @@ "@deephaven/plugin": "0.75.0", "@deephaven/utils": "0.75.0", "deep-equal": "^2.2.1", + "nanoid": "^5.0.7", "plotly.js": "^2.29.1", "plotly.js-dist-min": "^2.29.1", "react-plotly.js": "^2.4.0", - "react-redux": "^7.2.9", - "shortid": "^2.2.16" + "react-redux": "^7.2.9" }, "devDependencies": { "@deephaven/jsapi-types": "1.0.0-dev0.34.0", @@ -32121,10 +32134,10 @@ "@deephaven/jsapi-types": "^0.40.0", "@deephaven/log": "^0.40.0", "@deephaven/utils": "^0.40.0", + "nanoid": "^5.0.7", "plotly.js-dist-min": "^2.29.1", "prop-types": "^15.8.1", - "react-plotly.js": "^2.4.0", - "shortid": "^2.2.16" + "react-plotly.js": "^2.4.0" }, "devDependencies": { "@types/react": "^17.0.2", @@ -32185,27 +32198,27 @@ "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", "json-rpc-2.0": "^1.6.0", - "react-redux": "^7.x", - "shortid": "^2.2.16" + "nanoid": "^5.0.7", + "react-redux": "^7.x" }, "devDependencies": { "@types/react": "^17.0.2", @@ -32220,83 +32233,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 +32267,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 +32306,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 +32334,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 +32384,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 +32443,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 +32492,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 +32523,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 +32535,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 +32576,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 +32653,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 +32683,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 +32709,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 +32724,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 +32745,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 +32784,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 +32805,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 +32840,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 +32851,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", @@ -32811,25 +32864,10 @@ "url": "https://github.com/sponsors/mysticatea" } }, - "plugins/ui/src/js/node_modules/nanoid": { - "version": "5.0.7", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.js" - }, - "engines": { - "node": "^18 || >=20" - } - }, "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" } @@ -35095,10 +35133,10 @@ "@deephaven/log": "^0.40.0", "@types/react": "^17.0.2", "@vitejs/plugin-react-swc": "^3.0.0", + "nanoid": "^5.0.7", "react": "^17.0.2", "react-json-view": "^1.21.3", "sass": "^1.60.0", - "shortid": "^2.2.16", "typescript": "^4.5.4", "vite": "~4.1.4" }, @@ -35583,7 +35621,6 @@ "@types/react-dom": "^17.0.2", "@vitejs/plugin-react-swc": "^3.0.0", "react": "^17.0.2", - "shortid": "^2.2.16", "typescript": "^4.5.4", "vite": "~4.1.4" }, @@ -35835,11 +35872,11 @@ "@deephaven/utils": "^0.40.0", "@types/react": "^17.0.2", "@vitejs/plugin-react-swc": "^3.0.0", + "nanoid": "^5.0.7", "plotly.js-dist-min": "^2.29.1", "prop-types": "^15.8.1", "react": "^17.0.2", "react-plotly.js": "^2.4.0", - "shortid": "^2.2.16", "typescript": "^4.5.4", "vite": "~4.1.4" }, @@ -35870,13 +35907,13 @@ "@types/react-plotly.js": "^2.6.0", "@vitejs/plugin-react-swc": "^3.0.0", "deep-equal": "^2.2.1", + "nanoid": "^5.0.7", "plotly.js": "^2.29.1", "plotly.js-dist-min": "^2.29.1", "react": "^17.0.2", "react-dom": "^17.0.2", "react-plotly.js": "^2.4.0", "react-redux": "^7.2.9", - "shortid": "^2.2.16", "typescript": "^4.5.4", "vite": "~4.1.4" }, @@ -36250,106 +36287,47 @@ "@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", "@vitejs/plugin-react-swc": "^3.0.0", "classnames": "^2.5.1", "json-rpc-2.0": "^1.6.0", + "nanoid": "^5.0.7", "react": "^17.0.2", "react-dom": "^17.0.2", "react-redux": "^7.x", - "shortid": "^2.2.16", "typescript": "^4.5.4", "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 +36345,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 +36377,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 +36450,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 +36545,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 +36587,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 +36672,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,21 +36792,24 @@ }, "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" }, - "nanoid": { - "version": "5.0.7" - }, "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": { @@ -42251,10 +42342,6 @@ "version": "7.5.6", "dev": true }, - "@types/shortid": { - "version": "0.0.29", - "dev": true - }, "@types/stack-utils": { "version": "2.0.3", "dev": true @@ -50011,8 +50098,9 @@ "dev": true }, "nanoid": { - "version": "3.3.7", - "dev": true + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz", + "integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==" }, "native-promise-only": { "version": "0.8.1" @@ -51373,6 +51461,14 @@ "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.2.0" + }, + "dependencies": { + "nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true + } } }, "postcss-resolve-nested-selector": { @@ -51521,7 +51617,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 +51627,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/package.json b/package.json index cced88b7d..74105aff8 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "@types/jest": "^29.2.5", "@types/node": "^20.11.17", "@types/prop-types": "^15.7.10", - "@types/shortid": "^0.0.29", "eslint": "^8.37.0", "identity-obj-proxy": "^3.0.0", "jest": "^29.6.2", diff --git a/plugins/dashboard-object-viewer/src/js/package.json b/plugins/dashboard-object-viewer/src/js/package.json index 31edb95b3..8fdd4c665 100644 --- a/plugins/dashboard-object-viewer/src/js/package.json +++ b/plugins/dashboard-object-viewer/src/js/package.json @@ -23,8 +23,8 @@ "@deephaven/dashboard": "^0.40.0", "@deephaven/jsapi-types": "^0.40.0", "@deephaven/log": "^0.40.0", - "react-json-view": "^1.21.3", - "shortid": "^2.2.16" + "nanoid": "^5.0.7", + "react-json-view": "^1.21.3" }, "devDependencies": { "@types/react": "^17.0.2", diff --git a/plugins/dashboard-object-viewer/src/js/src/DashboardPlugin/DashboardPlugin.tsx b/plugins/dashboard-object-viewer/src/js/src/DashboardPlugin/DashboardPlugin.tsx index fde21fa0b..75e6c4cad 100644 --- a/plugins/dashboard-object-viewer/src/js/src/DashboardPlugin/DashboardPlugin.tsx +++ b/plugins/dashboard-object-viewer/src/js/src/DashboardPlugin/DashboardPlugin.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useEffect } from 'react'; -import shortid from 'shortid'; +import { nanoid } from 'nanoid'; import type { DashboardPluginComponentProps } from '@deephaven/dashboard'; import LayoutUtils from '@deephaven/dashboard/dist/layout/LayoutUtils'; import { useListener } from '@deephaven/dashboard/dist/layout/hooks'; @@ -19,7 +19,7 @@ export function DashboardPlugin({ ({ dragEvent, fetch, - panelId = shortid.generate(), + panelId = nanoid(), widget, }: { dragEvent?: DragEvent; diff --git a/plugins/matplotlib/src/js/package.json b/plugins/matplotlib/src/js/package.json index 6d4fcd9c0..67e63e177 100644 --- a/plugins/matplotlib/src/js/package.json +++ b/plugins/matplotlib/src/js/package.json @@ -43,8 +43,7 @@ "@deephaven/jsapi-bootstrap": "^0.58.0", "@deephaven/jsapi-types": "^0.58.0", "@deephaven/log": "^0.58.0", - "@deephaven/plugin": "^0.58.0", - "shortid": "^2.2.16" + "@deephaven/plugin": "^0.58.0" }, "publishConfig": { "access": "public" diff --git a/plugins/plotly-express/src/deephaven/plot/express/data/data_generators.py b/plugins/plotly-express/src/deephaven/plot/express/data/data_generators.py index 0acef0370..cf3c6ae66 100644 --- a/plugins/plotly-express/src/deephaven/plot/express/data/data_generators.py +++ b/plugins/plotly-express/src/deephaven/plot/express/data/data_generators.py @@ -110,10 +110,10 @@ def get_index(species: str) -> int: "timestamp = base_time + (long)((ii + df_len) * SECOND)", # pick a random species from the list, using the index as a seed "species = (String)species_list[(int)new Random(ii).nextInt(3)]", - "sepal_length = get_random_value(`sepal_length`, ii, species)", - "sepal_width = get_random_value(`sepal_width`, ii, species)", - "petal_length = get_random_value(`petal_length`, ii, species)", - "petal_width = get_random_value(`petal_width`, ii, species)", + "sepal_length = get_random_value(`sepal_length`, ii + 1, species)", + "sepal_width = get_random_value(`sepal_width`, ii + 2, species)", + "petal_length = get_random_value(`petal_length`, ii + 3, species)", + "petal_width = get_random_value(`petal_width`, ii + 4, species)", "species_id = get_index(species)", ] ) @@ -125,6 +125,135 @@ def get_index(species: str) -> int: return source_table +def jobs(ticking: bool = True) -> Table: + """ + Returns a synthetic dataset containing five different jobs and their durations over time. + + This dataset is intended to be used with a timeline plot. It demonstrates five different "jobs", each starting + two days after the previous, and each lasting 5 days in total. The job's "resource", or the name of the individual + assigned to the job, is randomly selected. The dataset continues to loop in this way, moving across time until + it is deleted or the server is shut down. + + Notes: + Contains the following columns: + - Job: a string column denoting the name of the job, ranging from Job1 to Job5 + - StartTime: a Java Instant column containing the start time of the job + - EndTime: a Java Instant column containing the end time of the job + - Resource: a string column indicating the name of the person that the job is assigned to + + Args: + ticking: + If true, the table will tick new data every second. + + Returns: + A Deephaven Table + + Examples: + ``` + from deephaven.plot import express as dx + jobs = dx.data.jobs() + ``` + """ + + def generate_resource(index: int) -> str: + random.seed(index) + return random.choice(["Mike", "Matti", "Steve", "John", "Jane"]) + + jobs_query_strings = [ + "Job = `Job` + String.valueOf((ii % 5) + 1)", + "StartTime = '2020-01-01T00:00:00Z' + ('P1d' * i * 2)", + "EndTime = StartTime + 'P5d'", + "Resource = generate_resource(ii)", + ] + + static_jobs = empty_table(5).update(jobs_query_strings) + + if not ticking: + return static_jobs + + ticking_jobs = merge( + [ + static_jobs, + time_table("PT1s") + .drop_columns("Timestamp") + .update(jobs_query_strings) + .update("StartTime = StartTime + 'P10d'"), + ] + ).last_by("Job") + + return ticking_jobs + + +def marketing(ticking: bool = True) -> Table: + """ + Returns a synthetic ticking dataset tracking the movement of customers from website visit to product purchase. + + This dataset is intended to be used with the `dx.funnel` and `dx.funnel_area` plot types. Each row in this dataset + represents an individual that has visited a company website. The individual may download an instance of the product, + be considered a potential customer, formally request the price of the product, or purchase the product and receive + an invoice. Each of these categories is a strict subset of the last, so it lends itself well to funnel plots. + + Notes: + Contains the following columns: + - Stage: a string column containing the stage of a customers interest: + VisitedWebsite, Downloaded, PotentialCustomer, RequestedPrice, and InvoiceSent + - Count: an integer column counting the number of customers to fall into each category + + Args: + ticking: + If true, the table will tick new data every second. + + Returns: + A Deephaven Table + + Examples: + ``` + from deephaven.plot import express as dx + marketing = dx.data.marketing() + ``` + """ + _ColsToRowsTransform = jpy.get_type( + "io.deephaven.engine.table.impl.util.ColumnsToRowsTransform" + ) + + def weighted_selection(prob: float, index: int) -> bool: + random.seed(index) + return random.uniform(0, 1) < prob + + marketing_query_strings = [ + "VisitedWebsite = true", # appearing in this table assumes a website visit + "Downloaded = VisitedWebsite ? weighted_selection(0.45, ii) : false", # 45% of visits download product + "PotentialCustomer = Downloaded ? weighted_selection(0.77, ii + 1) : false", # 77% of downloads are potential customers + "RequestedPrice = PotentialCustomer ? weighted_selection(0.82, ii + 2) : false", # 82% of flagged potential customers request price + "InvoiceSent = RequestedPrice ? weighted_selection(0.24, ii + 3) : false", # 24% of those who requested price get invoice + ] + + marketing_table = empty_table(100).update(marketing_query_strings) + + if ticking: + marketing_table = merge( + [ + marketing_table, + time_table("PT1s") + .update(marketing_query_strings) + .drop_columns("Timestamp"), + ] + ) + + return Table( + _ColsToRowsTransform.columnsToRows( + marketing_table.sum_by().j_table, + "Stage", + "Count", + "VisitedWebsite", + "Downloaded", + "PotentialCustomer", + "RequestedPrice", + "InvoiceSent", + ) + ) + + def stocks(ticking: bool = True, hours_of_data: int = 1) -> Table: """Returns a Deephaven table containing a generated example data set. @@ -353,23 +482,23 @@ def generate_sex(index: int) -> str: return random.choices(sex_list, weights=sex_probs)[0] def generate_smoker(index: int) -> str: - random.seed(index) + random.seed(index + 1) return random.choices(smoker_list, weights=smoker_probs)[0] def generate_day(index: int) -> str: - random.seed(index) + random.seed(index + 2) return random.choices(day_list, weights=day_probs)[0] def generate_time(index: int) -> str: - random.seed(index) + random.seed(index + 3) return random.choices(time_list, weights=time_probs)[0] def generate_size(index: int) -> int: - random.seed(index) + random.seed(index + 4) return random.choices(size_list, weights=size_probs)[0] def generate_total_bill(smoker: str, size: int, index: int) -> float: - random.seed(index) + random.seed(index + 5) return round( 3.68 + 3.08 * (smoker == "Yes") @@ -379,7 +508,7 @@ def generate_total_bill(smoker: str, size: int, index: int) -> float: ) def generate_tip(total_bill: float, index: int) -> float: - random.seed(index) + random.seed(index + 6) return max(1, round(0.92 + 0.11 * total_bill + random.gauss(0.0, 1.02), 2)) # create synthetic ticking version of the tips dataset that generates one new observation per period @@ -403,7 +532,7 @@ def generate_tip(total_bill: float, index: int) -> float: return merge([tips_table, ticking_table]) -def election(ticking: bool = True): +def election(ticking: bool = True) -> Table: """ Returns a ticking version of the Election dataset included in the plotly-express package. @@ -488,7 +617,7 @@ def get_long_val(column: str, index: int) -> int: return merge([election_table.head(STATIC_ROWS - 1), ticking_table]) -def wind(ticking: bool = True): +def wind(ticking: bool = True) -> Table: """ Returns a ticking version of the Wind dataset included in the plotly-express package. diff --git a/plugins/plotly-express/src/deephaven/plot/express/plots/bar.py b/plugins/plotly-express/src/deephaven/plot/express/plots/bar.py index 372763d9e..ed67460f7 100644 --- a/plugins/plotly-express/src/deephaven/plot/express/plots/bar.py +++ b/plugins/plotly-express/src/deephaven/plot/express/plots/bar.py @@ -1,6 +1,5 @@ from __future__ import annotations -from numbers import Number from typing import Callable from plotly import express as px @@ -38,8 +37,8 @@ def bar( | dict[str | tuple[str], str] | None = None, color_continuous_scale: list[str] | None = None, - range_color: list[Number] | None = None, - color_continuous_midpoint: Number | None = None, + range_color: list[float] | None = None, + color_continuous_midpoint: float | None = None, opacity: float | None = None, barmode: str = "relative", log_x: bool = False, @@ -221,8 +220,8 @@ def timeline( | dict[str | tuple[str], str] | None = None, color_continuous_scale: list[str] | None = None, - range_color: list[Number] | None = None, - color_continuous_midpoint: Number | None = None, + range_color: list[float] | None = None, + color_continuous_midpoint: float | None = None, opacity: float | None = None, range_x: list[int] | None = None, range_y: list[int] | None = None, diff --git a/plugins/plotly-express/src/deephaven/plot/express/plots/hierarchial.py b/plugins/plotly-express/src/deephaven/plot/express/plots/hierarchial.py index ce6295695..3654b9a69 100644 --- a/plugins/plotly-express/src/deephaven/plot/express/plots/hierarchial.py +++ b/plugins/plotly-express/src/deephaven/plot/express/plots/hierarchial.py @@ -1,6 +1,5 @@ from __future__ import annotations -from numbers import Number from typing import Callable from plotly import express as px @@ -23,8 +22,8 @@ def treemap( color_discrete_sequence: list[str] | None = None, color_discrete_map: dict[str | tuple[str], str] | None = None, color_continuous_scale: list[str] | None = None, - range_color: list[Number] | None = None, - color_continuous_midpoint: Number | None = None, + range_color: list[float] | None = None, + color_continuous_midpoint: float | None = None, labels: dict[str, str] | None = None, title: str | None = None, template: str | None = None, @@ -91,8 +90,8 @@ def sunburst( color_discrete_sequence: list[str] | None = None, color_discrete_map: dict[str | tuple[str], str] | None = None, color_continuous_scale: list[str] | None = None, - range_color: list[Number] | None = None, - color_continuous_midpoint: Number | None = None, + range_color: list[float] | None = None, + color_continuous_midpoint: float | None = None, labels: dict[str, str] | None = None, title: str | None = None, template: str | None = None, @@ -159,8 +158,8 @@ def icicle( color_discrete_sequence: list[str] | None = None, color_discrete_map: dict[str | tuple[str], str] | None = None, color_continuous_scale: list[str] | None = None, - range_color: list[Number] | None = None, - color_continuous_midpoint: Number | None = None, + range_color: list[float] | None = None, + color_continuous_midpoint: float | None = None, labels: dict[str, str] | None = None, title: str | None = None, template: str | None = None, diff --git a/plugins/plotly-express/src/deephaven/plot/express/plots/maps.py b/plugins/plotly-express/src/deephaven/plot/express/plots/maps.py index 61af14358..2557b84d7 100644 --- a/plugins/plotly-express/src/deephaven/plot/express/plots/maps.py +++ b/plugins/plotly-express/src/deephaven/plot/express/plots/maps.py @@ -1,6 +1,5 @@ from __future__ import annotations -from numbers import Number from typing import Callable from plotly import express as px @@ -41,8 +40,8 @@ def scatter_geo( | dict[str | tuple[str], str] | None = None, color_continuous_scale: list[str] | None = None, - range_color: list[Number] | None = None, - color_continuous_midpoint: Number | None = None, + range_color: list[float] | None = None, + color_continuous_midpoint: float | None = None, opacity: float | None = None, projection: str | None = None, scope: str | None = None, @@ -175,8 +174,8 @@ def scatter_mapbox( | dict[str | tuple[str], str] | None = None, color_continuous_scale: list[str] | None = None, - range_color: list[Number] | None = None, - color_continuous_midpoint: Number | None = None, + range_color: list[float] | None = None, + color_continuous_midpoint: float | None = None, opacity: float | None = None, zoom: float | None = None, center: dict[str, float] | None = None, diff --git a/plugins/plotly-express/src/deephaven/plot/express/plots/scatter.py b/plugins/plotly-express/src/deephaven/plot/express/plots/scatter.py index 71e20f44f..6ba28acd4 100644 --- a/plugins/plotly-express/src/deephaven/plot/express/plots/scatter.py +++ b/plugins/plotly-express/src/deephaven/plot/express/plots/scatter.py @@ -1,6 +1,5 @@ from __future__ import annotations -from numbers import Number from typing import Callable from plotly import express as px @@ -44,8 +43,8 @@ def scatter( | dict[str | tuple[str], str] | None = None, color_continuous_scale: list[str] | None = None, - range_color: list[Number] | None = None, - color_continuous_midpoint: Number | None = None, + range_color: list[float] | None = None, + color_continuous_midpoint: float | None = None, xaxis_sequence: list[int] | None = None, yaxis_sequence: list[int] | None = None, opacity: float | None = None, @@ -221,8 +220,8 @@ def scatter_3d( | dict[str | tuple[str], str] | None = None, color_continuous_scale: list[str] | None = None, - range_color: list[Number] | None = None, - color_continuous_midpoint: Number | None = None, + range_color: list[float] | None = None, + color_continuous_midpoint: float | None = None, opacity: float | None = None, log_x: bool = False, log_y: bool = False, @@ -367,8 +366,8 @@ def scatter_polar( | dict[str | tuple[str], str] | None = None, color_continuous_scale: list[str] | None = None, - range_color: list[Number] | None = None, - color_continuous_midpoint: Number | None = None, + range_color: list[float] | None = None, + color_continuous_midpoint: float | None = None, opacity: float | None = None, direction: str = "clockwise", start_angle: int = 90, @@ -493,8 +492,8 @@ def scatter_ternary( | dict[str | tuple[str], str] | None = None, color_continuous_scale: list[str] | None = None, - range_color: list[Number] | None = None, - color_continuous_midpoint: Number | None = None, + range_color: list[float] | None = None, + color_continuous_midpoint: float | None = None, opacity: float | None = None, title: str | None = None, template: str | None = None, diff --git a/plugins/plotly-express/src/js/package.json b/plugins/plotly-express/src/js/package.json index 5a22602d1..e0aac7a72 100644 --- a/plugins/plotly-express/src/js/package.json +++ b/plugins/plotly-express/src/js/package.json @@ -63,11 +63,11 @@ "@deephaven/plugin": "0.75.0", "@deephaven/utils": "0.75.0", "deep-equal": "^2.2.1", + "nanoid": "^5.0.7", "plotly.js": "^2.29.1", "plotly.js-dist-min": "^2.29.1", "react-plotly.js": "^2.4.0", - "react-redux": "^7.2.9", - "shortid": "^2.2.16" + "react-redux": "^7.2.9" }, "publishConfig": { "access": "public" diff --git a/plugins/plotly-express/src/js/src/DashboardPlugin.tsx b/plugins/plotly-express/src/js/src/DashboardPlugin.tsx index 1774d9f3f..b6560a393 100644 --- a/plugins/plotly-express/src/js/src/DashboardPlugin.tsx +++ b/plugins/plotly-express/src/js/src/DashboardPlugin.tsx @@ -1,5 +1,5 @@ import { useCallback, DragEvent, useEffect } from 'react'; -import shortid from 'shortid'; +import { nanoid } from 'nanoid'; import { DashboardPluginComponentProps, LayoutUtils, @@ -20,7 +20,7 @@ export function DashboardPlugin( dragEvent, fetch, metadata = {}, - panelId = shortid.generate(), + panelId = nanoid(), widget, }: { dragEvent?: DragEvent; diff --git a/plugins/plotly/src/js/package.json b/plugins/plotly/src/js/package.json index 68059ff86..65836d11f 100644 --- a/plugins/plotly/src/js/package.json +++ b/plugins/plotly/src/js/package.json @@ -40,10 +40,10 @@ "@deephaven/jsapi-types": "^0.40.0", "@deephaven/log": "^0.40.0", "@deephaven/utils": "^0.40.0", + "nanoid": "^5.0.7", "plotly.js-dist-min": "^2.29.1", "prop-types": "^15.8.1", - "react-plotly.js": "^2.4.0", - "shortid": "^2.2.16" + "react-plotly.js": "^2.4.0" }, "publishConfig": { "access": "public" diff --git a/plugins/plotly/src/js/src/DashboardPlugin.tsx b/plugins/plotly/src/js/src/DashboardPlugin.tsx index e36b6cc6a..2aa1541a6 100644 --- a/plugins/plotly/src/js/src/DashboardPlugin.tsx +++ b/plugins/plotly/src/js/src/DashboardPlugin.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect } from 'react'; -import shortid from 'shortid'; +import { nanoid } from 'nanoid'; import { DashboardPluginComponentProps, LayoutUtils, @@ -27,7 +27,7 @@ export function DashboardPlugin( dragEvent, fetch, metadata = {}, - panelId = shortid.generate(), + panelId = nanoid(), widget, }: { dragEvent?: React.DragEvent; 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/action_button.py b/plugins/ui/src/deephaven/ui/components/action_button.py index 3f31fc5dc..faef01337 100644 --- a/plugins/ui/src/deephaven/ui/components/action_button.py +++ b/plugins/ui/src/deephaven/ui/components/action_button.py @@ -17,7 +17,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, ) @@ -45,12 +44,12 @@ def action_button( is_quiet: bool | None = None, static_color: StaticColor | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -78,7 +77,7 @@ def action_button( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, exclude_from_tab_order: bool | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/action_group.py b/plugins/ui/src/deephaven/ui/components/action_group.py index f167892ee..6e4bc2024 100644 --- a/plugins/ui/src/deephaven/ui/components/action_group.py +++ b/plugins/ui/src/deephaven/ui/components/action_group.py @@ -1,5 +1,4 @@ from __future__ import annotations -from numbers import Number from typing import Any, Callable, Iterable @@ -43,12 +42,12 @@ def action_group( on_change: Callable[[Key], None] | None = None, on_selection_change: Callable[[Selection], None] | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_column: str | None = None, @@ -76,7 +75,7 @@ def action_group( right: DimensionValue | None = None, start: DimensionValue | None = None, end: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, aria_label: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/action_menu.py b/plugins/ui/src/deephaven/ui/components/action_menu.py index 9b8601853..640dae31d 100644 --- a/plugins/ui/src/deephaven/ui/components/action_menu.py +++ b/plugins/ui/src/deephaven/ui/components/action_menu.py @@ -1,5 +1,4 @@ from __future__ import annotations -from numbers import Number from typing import Callable, Iterable from .item import Item @@ -45,12 +44,12 @@ def action_menu( on_action: Callable[[ActionKey], None] | None = None, on_open_change: Callable[[bool], None] | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -78,7 +77,7 @@ def action_menu( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, aria_label: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/button.py b/plugins/ui/src/deephaven/ui/components/button.py index d13d7cab6..fe6e5b135 100644 --- a/plugins/ui/src/deephaven/ui/components/button.py +++ b/plugins/ui/src/deephaven/ui/components/button.py @@ -20,7 +20,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, ) from .basic import component_element @@ -51,12 +50,12 @@ def button( on_key_down: KeyboardEventCallable | None = None, on_key_up: KeyboardEventCallable | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_column: str | None = None, grid_row: str | None = None, @@ -84,7 +83,7 @@ def button( right: DimensionValue | None = None, start: DimensionValue | None = None, end: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, exclude_from_tab_order: bool | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/button_group.py b/plugins/ui/src/deephaven/ui/components/button_group.py index 8f08d78ad..d88d1a09a 100644 --- a/plugins/ui/src/deephaven/ui/components/button_group.py +++ b/plugins/ui/src/deephaven/ui/components/button_group.py @@ -9,7 +9,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, ) from .basic import component_element @@ -22,12 +21,12 @@ def button_group( orientation: Orientation = "horizontal", alignment: AlignSelf = "start", flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_column: str | None = None, @@ -55,7 +54,7 @@ def button_group( right: DimensionValue | None = None, start: DimensionValue | None = None, end: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, UNSAFE_class_name: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/checkbox.py b/plugins/ui/src/deephaven/ui/components/checkbox.py index e9818d780..33b77c62d 100644 --- a/plugins/ui/src/deephaven/ui/components/checkbox.py +++ b/plugins/ui/src/deephaven/ui/components/checkbox.py @@ -11,7 +11,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, ) from .basic import component_element @@ -40,12 +39,12 @@ def checkbox( on_key_down: KeyboardEventCallable | None = None, on_key_up: KeyboardEventCallable | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -73,7 +72,7 @@ def checkbox( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, exclude_from_tab_order: bool | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/combo_box.py b/plugins/ui/src/deephaven/ui/components/combo_box.py index 41b21bc09..fc77072c0 100644 --- a/plugins/ui/src/deephaven/ui/components/combo_box.py +++ b/plugins/ui/src/deephaven/ui/components/combo_box.py @@ -6,7 +6,6 @@ FocusEventCallable, KeyboardEventCallable, LayoutFlex, - Number, DimensionValue, AlignSelf, JustifySelf, @@ -85,12 +84,12 @@ def combo_box( on_key_down: Callable[[KeyboardEventCallable], None] | None = None, on_key_up: Callable[[KeyboardEventCallable], None] | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -118,7 +117,7 @@ def combo_box( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, aria_label: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/content.py b/plugins/ui/src/deephaven/ui/components/content.py index dd7e27130..5db0f1062 100644 --- a/plugins/ui/src/deephaven/ui/components/content.py +++ b/plugins/ui/src/deephaven/ui/components/content.py @@ -7,7 +7,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, ) from .basic import component_element @@ -17,12 +16,12 @@ def content( *children: Any, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -50,7 +49,7 @@ def content( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, UNSAFE_class_name: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/contextual_help.py b/plugins/ui/src/deephaven/ui/components/contextual_help.py index 95e3cc155..c509b23a8 100644 --- a/plugins/ui/src/deephaven/ui/components/contextual_help.py +++ b/plugins/ui/src/deephaven/ui/components/contextual_help.py @@ -1,5 +1,4 @@ from __future__ import annotations -from numbers import Number from typing import Any, Callable from .types import ( # Validation @@ -23,18 +22,18 @@ def contextual_help( placement: Placement | None = "bottom start", is_open: bool | None = None, default_open: bool | None = None, - container_padding: Number | None = None, - offset: Number | None = None, - cross_offset: Number | None = None, + container_padding: float | None = None, + offset: float | None = None, + cross_offset: float | None = None, should_flip: bool | None = None, on_open_change: Callable[[bool], None] | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_column: str | None = None, @@ -62,7 +61,7 @@ def contextual_help( right: DimensionValue | None = None, start: DimensionValue | None = None, end: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, aria_label: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/date_picker.py b/plugins/ui/src/deephaven/ui/components/date_picker.py index 255ec472d..51e47e131 100644 --- a/plugins/ui/src/deephaven/ui/components/date_picker.py +++ b/plugins/ui/src/deephaven/ui/components/date_picker.py @@ -6,7 +6,6 @@ FocusEventCallable, KeyboardEventCallable, LayoutFlex, - Number, DimensionValue, AlignSelf, JustifySelf, @@ -112,12 +111,12 @@ def date_picker( on_open_change: Callable[[bool], None] | None = None, on_change: Callable[[Date], None] | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -145,7 +144,7 @@ def date_picker( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, aria_label: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/form.py b/plugins/ui/src/deephaven/ui/components/form.py index fc71dfdf3..ea622ebeb 100644 --- a/plugins/ui/src/deephaven/ui/components/form.py +++ b/plugins/ui/src/deephaven/ui/components/form.py @@ -7,7 +7,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, ValidationState, ValidationBehavior, @@ -48,12 +47,12 @@ def form( # on_reset, # on_invalid, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -82,7 +81,7 @@ def form( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, aria_label: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/grid.py b/plugins/ui/src/deephaven/ui/components/grid.py index 56a60f943..32a43ea94 100644 --- a/plugins/ui/src/deephaven/ui/components/grid.py +++ b/plugins/ui/src/deephaven/ui/components/grid.py @@ -7,7 +7,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, GridFlow, JustifyItems, @@ -35,12 +34,12 @@ def grid( column_gap: DimensionValue | None = None, row_gap: DimensionValue | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -68,7 +67,7 @@ def grid( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, UNSAFE_class_name: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/heading.py b/plugins/ui/src/deephaven/ui/components/heading.py index 39a21e1f4..86d657030 100644 --- a/plugins/ui/src/deephaven/ui/components/heading.py +++ b/plugins/ui/src/deephaven/ui/components/heading.py @@ -7,7 +7,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, HeadingLevel, ) @@ -19,12 +18,12 @@ def heading( *children: Any, level: HeadingLevel = 3, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -52,7 +51,7 @@ def heading( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, UNSAFE_class_name: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/illustrated_message.py b/plugins/ui/src/deephaven/ui/components/illustrated_message.py index 9733b45fb..ac99d327b 100644 --- a/plugins/ui/src/deephaven/ui/components/illustrated_message.py +++ b/plugins/ui/src/deephaven/ui/components/illustrated_message.py @@ -1,5 +1,4 @@ from __future__ import annotations -from numbers import Number from typing import Any from .types import ( AlignSelf, @@ -16,12 +15,12 @@ def illustrated_message( *children: Any, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_column: str | None = None, @@ -49,7 +48,7 @@ def illustrated_message( right: DimensionValue | None = None, start: DimensionValue | None = None, end: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, UNSAFE_class_name: str | None = None, @@ -100,20 +99,21 @@ def illustrated_message( UNSAFE_style: Set the inline style for the element. Only use as a last resort. Use style props instead. Examples: - prompt = ui.illustrated_message( - ui.heading("Enter URL above"), - ui.content("Enter a URL of a CSV above and click 'Load' to load it"), + no_results = ui.illustrated_message( + ui.heading("No Results"), + ui.content("Try another search"), ) warning = ui.illustrated_message( ui.icon("vsWarning"), - ui.heading("Warning"), - ui.content("This is a warning message."), + ui.heading("Invalid input"), + ui.content("No special characters allowed."), ) error_message = ui.illustrated_message( - ui.icon("vsWarning", size="XXL", margin_bottom="size-10"), - ui.heading("Invalid Input"), - ui.content("Please enter 'Sym' and 'Exchange' above"), + ui.icon("vsError"), + ui.heading("Access denied"), + ui.content("You do not have permissions to access this page."), ) + """ return component_element( "IllustratedMessage", diff --git a/plugins/ui/src/deephaven/ui/components/list_action_group.py b/plugins/ui/src/deephaven/ui/components/list_action_group.py index 2c35ec9a1..45831594c 100644 --- a/plugins/ui/src/deephaven/ui/components/list_action_group.py +++ b/plugins/ui/src/deephaven/ui/components/list_action_group.py @@ -1,6 +1,5 @@ from __future__ import annotations -from numbers import Number from typing import Callable, Iterable from .basic import component_element @@ -52,12 +51,12 @@ def list_action_group( selected_keys: SelectedKeys | Iterable[str] | None = None, default_selected_keys: SelectedKeys | Iterable[str] | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_column: str | None = None, @@ -85,7 +84,7 @@ def list_action_group( right: DimensionValue | None = None, start: DimensionValue | None = None, end: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, aria_label: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/list_action_menu.py b/plugins/ui/src/deephaven/ui/components/list_action_menu.py index 95137b306..d61d18bf1 100644 --- a/plugins/ui/src/deephaven/ui/components/list_action_menu.py +++ b/plugins/ui/src/deephaven/ui/components/list_action_menu.py @@ -1,7 +1,6 @@ from __future__ import annotations -from numbers import Number -from typing import Callable, Iterable, Union +from typing import Callable, Iterable from .basic import component_element @@ -40,12 +39,12 @@ def list_action_menu( is_open: bool | None = None, default_open: bool | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -73,7 +72,7 @@ def list_action_menu( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, aria_label: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/number_field.py b/plugins/ui/src/deephaven/ui/components/number_field.py index 6a13ad07d..82d4f0c39 100644 --- a/plugins/ui/src/deephaven/ui/components/number_field.py +++ b/plugins/ui/src/deephaven/ui/components/number_field.py @@ -13,7 +13,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, LabelPosition, Align, @@ -56,12 +55,12 @@ def number_field( on_key_up: KeyboardEventCallable | None = None, on_change: Callable[[float], None] | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -89,7 +88,7 @@ def number_field( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, aria_label: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/range_slider.py b/plugins/ui/src/deephaven/ui/components/range_slider.py index 9587abe95..2fdf4e8cd 100644 --- a/plugins/ui/src/deephaven/ui/components/range_slider.py +++ b/plugins/ui/src/deephaven/ui/components/range_slider.py @@ -11,7 +11,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, LabelPosition, ) @@ -29,9 +28,9 @@ def range_slider( contextual_help: Any | None = None, orientation: Orientation = "horizontal", is_disabled: bool | None = None, - min_value: Number = 0, - max_value: Number = 100, - step: Number = 1, + min_value: float = 0, + max_value: float = 100, + step: float = 1, value: SliderChange | None = None, default_value: SliderChange | None = None, label: Any | None = None, @@ -39,12 +38,12 @@ def range_slider( on_change_end: SliderChangeCallable | None = None, on_change: SliderChangeCallable | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -72,7 +71,7 @@ def range_slider( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, aria_label: str | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/slider.py b/plugins/ui/src/deephaven/ui/components/slider.py index e15f8675f..cf8b60ad7 100644 --- a/plugins/ui/src/deephaven/ui/components/slider.py +++ b/plugins/ui/src/deephaven/ui/components/slider.py @@ -9,7 +9,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, LabelPosition, ) @@ -19,7 +18,7 @@ def slider( is_filled: bool | None = None, - fill_offset: Number | None = None, + fill_offset: float | None = None, track_gradient: list[str] | None = None, # format_options, # omitted because need to connect it to Deephaven formatting options as well label_position: LabelPosition = "top", @@ -28,22 +27,22 @@ def slider( contextual_help: Any | None = None, orientation: Orientation = "horizontal", is_disabled: bool | None = None, - min_value: Number = 0, - max_value: Number = 100, - step: Number = 1, - value: Number | None = None, - default_value: Number | None = None, + min_value: float = 0, + max_value: float = 100, + step: float = 1, + value: float | None = None, + default_value: float | None = None, label: Any | None = None, name: str | None = None, - on_change_end: Callable[[Number], None] | None = None, - on_change: Callable[[Number], None] | None = None, + on_change_end: Callable[[float], None] | None = None, + on_change: Callable[[float], None] | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -71,7 +70,7 @@ def slider( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, aria_label: str | None = None, 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/components/text_field.py b/plugins/ui/src/deephaven/ui/components/text_field.py index e8b84a99f..524626cd2 100644 --- a/plugins/ui/src/deephaven/ui/components/text_field.py +++ b/plugins/ui/src/deephaven/ui/components/text_field.py @@ -13,7 +13,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, LabelPosition, Align, @@ -58,12 +57,12 @@ def text_field( on_key_up: KeyboardEventCallable | None = None, on_change: Callable[[str], None] | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -91,7 +90,7 @@ def text_field( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, exclude_from_tab_order: bool | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/toggle_button.py b/plugins/ui/src/deephaven/ui/components/toggle_button.py index d86ce2ba5..a9a16c018 100644 --- a/plugins/ui/src/deephaven/ui/components/toggle_button.py +++ b/plugins/ui/src/deephaven/ui/components/toggle_button.py @@ -17,7 +17,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, ) from .basic import component_element @@ -46,12 +45,12 @@ def toggle_button( on_key_down: KeyboardEventCallable | None = None, on_key_up: KeyboardEventCallable | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_column: str | None = None, grid_row: str | None = None, @@ -79,7 +78,7 @@ def toggle_button( right: DimensionValue | None = None, start: DimensionValue | None = None, end: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, exclude_from_tab_order: bool | None = None, diff --git a/plugins/ui/src/deephaven/ui/components/types/layout.py b/plugins/ui/src/deephaven/ui/components/types/layout.py index 2acb4f8f3..3df229221 100644 --- a/plugins/ui/src/deephaven/ui/components/types/layout.py +++ b/plugins/ui/src/deephaven/ui/components/types/layout.py @@ -129,14 +129,12 @@ Alignment = Literal["start", "end"] -Number = Union[int, float] - -LayoutFlex = Union[str, Number, bool] +LayoutFlex = Union[str, float, bool] """ The flex CSS shorthand property sets how a flex item will grow or shrink to fit the space available in its flex container. """ -DimensionValue = Union[str, Number] +DimensionValue = Union[str, float] """ A dimension value can be a string providing a unit, such as "10px", or a number, which is assumed to be in pixels. """ diff --git a/plugins/ui/src/deephaven/ui/components/view.py b/plugins/ui/src/deephaven/ui/components/view.py index 25982a1e0..4d2abb8f2 100644 --- a/plugins/ui/src/deephaven/ui/components/view.py +++ b/plugins/ui/src/deephaven/ui/components/view.py @@ -12,7 +12,6 @@ DimensionValue, JustifySelf, LayoutFlex, - Number, Position, ) from .basic import component_element @@ -23,12 +22,12 @@ def view( *children: Any, element_type: ElementTypes | None = None, flex: LayoutFlex | None = None, - flex_grow: Number | None = None, - flex_shrink: Number | None = None, + flex_grow: float | None = None, + flex_shrink: float | None = None, flex_basis: DimensionValue | None = None, align_self: AlignSelf | None = None, justify_self: JustifySelf | None = None, - order: Number | None = None, + order: int | None = None, grid_area: str | None = None, grid_row: str | None = None, grid_row_start: str | None = None, @@ -84,7 +83,7 @@ def view( end: DimensionValue | None = None, left: DimensionValue | None = None, right: DimensionValue | None = None, - z_index: Number | None = None, + z_index: int | None = None, is_hidden: bool | None = None, id: str | None = None, UNSAFE_class_name: str | None = None, 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..1fa24888f 100644 --- a/plugins/ui/src/js/package.json +++ b/plugins/ui/src/js/package.json @@ -41,27 +41,27 @@ "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", "json-rpc-2.0": "^1.6.0", - "react-redux": "^7.x", - "shortid": "^2.2.16" + "nanoid": "^5.0.7", + "react-redux": "^7.x" }, "publishConfig": { "access": "public" diff --git a/plugins/ui/src/js/src/DashboardPlugin.tsx b/plugins/ui/src/js/src/DashboardPlugin.tsx index 5bf7417fb..0b22fc62e 100644 --- a/plugins/ui/src/js/src/DashboardPlugin.tsx +++ b/plugins/ui/src/js/src/DashboardPlugin.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import shortid from 'shortid'; +import { nanoid } from 'nanoid'; import { DashboardPluginComponentProps, LayoutManagerContext, @@ -77,7 +77,7 @@ export function DashboardPlugin( const handleWidgetOpen = useCallback( ({ - widgetId = shortid.generate(), + widgetId = nanoid(), widget, }: { widgetId: string; @@ -119,7 +119,7 @@ export function DashboardPlugin( const handlePanelOpen = useCallback( ({ - panelId: widgetId = shortid.generate(), + panelId: widgetId = nanoid(), widget, }: PanelOpenEventDetail) => { const { type } = widget; diff --git a/plugins/ui/src/js/src/elements/IllustratedMessage.tsx b/plugins/ui/src/js/src/elements/IllustratedMessage.tsx new file mode 100644 index 000000000..ba75de9e4 --- /dev/null +++ b/plugins/ui/src/js/src/elements/IllustratedMessage.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { + IllustratedMessage as DHCIllustratedMessage, + IllustratedMessageProps as DHCIllustratedMessageProps, + Icon, +} from '@deephaven/components'; +import { isElementOfType } from '@deephaven/react-hooks'; + +export function IllustratedMessage( + props: DHCIllustratedMessageProps +): JSX.Element { + const { children, ...otherProps } = props; + + /* eslint-disable-next-line react/jsx-props-no-spreading */ + if (children === undefined) return ; + + const newChildren = React.Children.map(children, element => { + if (isElementOfType(element, Icon) === true) { + const size = element.props.size ?? 'XXL'; + const marginBottom = + element.props.margin ?? + element.props.marginY ?? + element.props.marginBottom ?? + 'size-10'; + + return React.cloneElement(element, { + ...element.props, + size, + marginBottom, + }); + } + + return element; + }); + + return ( + /* eslint-disable-next-line react/jsx-props-no-spreading */ + {newChildren} + ); +} + +export default IllustratedMessage; 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/index.ts b/plugins/ui/src/js/src/elements/index.ts index d05cabf01..8302b4719 100644 --- a/plugins/ui/src/js/src/elements/index.ts +++ b/plugins/ui/src/js/src/elements/index.ts @@ -5,6 +5,7 @@ export * from './Form'; export * from './hooks'; export * from './HTMLElementView'; export * from './IconElementView'; +export * from './IllustratedMessage'; export * from './ListView'; export * from './model'; export * from './ObjectView'; 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/js/src/layout/ReactPanel.tsx b/plugins/ui/src/js/src/layout/ReactPanel.tsx index cf3fdebd0..914b7a7a5 100644 --- a/plugins/ui/src/js/src/layout/ReactPanel.tsx +++ b/plugins/ui/src/js/src/layout/ReactPanel.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import ReactDOM from 'react-dom'; -import shortid from 'shortid'; +import { nanoid } from 'nanoid'; import { LayoutUtils, PanelEvent, @@ -94,7 +94,7 @@ function ReactPanel({ // We want to regenerate the key every time the metadata changes, so that the portal is re-rendered // eslint-disable-next-line react-hooks/exhaustive-deps - const contentKey = useMemo(() => shortid.generate(), [metadata]); + const contentKey = useMemo(() => nanoid(), [metadata]); const parent = useParentItem(); const { eventHub } = layoutManager; diff --git a/plugins/ui/src/js/src/widget/DocumentHandler.tsx b/plugins/ui/src/js/src/widget/DocumentHandler.tsx index f0ae8a48e..7d4f3c400 100644 --- a/plugins/ui/src/js/src/widget/DocumentHandler.tsx +++ b/plugins/ui/src/js/src/widget/DocumentHandler.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useMemo, useRef, useState } from 'react'; -import shortid from 'shortid'; +import { nanoid } from 'nanoid'; import { WidgetDescriptor } from '@deephaven/dashboard'; import Log from '@deephaven/log'; import { EMPTY_FUNCTION } from '@deephaven/utils'; @@ -101,7 +101,7 @@ function DocumentHandler({ // If there are no more known IDs, generate a new one. // This can happen if the document hasn't been opened before, or if it's rehydrated and a new panel is added. // Note that if the order of panels changes, the worst case scenario is that panels appear in the wrong location in the layout. - const panelId = widgetData.panelIds?.[panelIdIndex.current] ?? shortid(); + const panelId = widgetData.panelIds?.[panelIdIndex.current] ?? nanoid(); panelIdIndex.current += 1; return panelId; }, [widgetData]); diff --git a/plugins/ui/src/js/src/widget/WidgetUtils.tsx b/plugins/ui/src/js/src/widget/WidgetUtils.tsx index ebec26892..ffee67c26 100644 --- a/plugins/ui/src/js/src/widget/WidgetUtils.tsx +++ b/plugins/ui/src/js/src/widget/WidgetUtils.tsx @@ -13,7 +13,6 @@ import { Flex, Grid, Heading, - IllustratedMessage, Item, ListActionGroup, ListActionMenu, @@ -53,6 +52,7 @@ import { ActionGroup, Button, Form, + IllustratedMessage, ListView, Picker, Radio, 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" } } } } diff --git a/ruff.toml b/ruff.toml index 96bed7376..b2c9ff227 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,5 +1,8 @@ [lint] -select = ["ANN001"] +select = ["ANN001", "TID251"] [lint.per-file-ignores] -"**/{test,matplotlib,json,plotly}/*" = ["ANN001"] \ No newline at end of file +"**/{test,matplotlib,json,plotly}/*" = ["ANN001"] + +[lint.flake8-tidy-imports.banned-api] +"numbers".msg = "Import from numbers is likely an accident. `float` includes `int` and is likely the desired type." \ No newline at end of file diff --git a/templates/widget/{{ cookiecutter.python_project_name }}/src/js/package-lock.json b/templates/widget/{{ cookiecutter.python_project_name }}/src/js/package-lock.json index 9f649285e..b67c4267d 100644 --- a/templates/widget/{{ cookiecutter.python_project_name }}/src/js/package-lock.json +++ b/templates/widget/{{ cookiecutter.python_project_name }}/src/js/package-lock.json @@ -177,7 +177,7 @@ "react-transition-group": "^4.4.2", "react-virtualized-auto-sizer": "1.0.6", "react-window": "^1.8.6", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "engines": { "node": ">=10" @@ -213,7 +213,7 @@ "popper.js": "^1.16.1", "prop-types": "^15.7.2", "shell-quote": "^1.7.2", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "engines": { "node": ">=16" @@ -238,7 +238,7 @@ "lodash.ismatch": "^4.1.1", "lodash.throttle": "^4.1.1", "prop-types": "^15.7.2", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "engines": { "node": ">=16" @@ -336,7 +336,7 @@ "prop-types": "^15.7.2", "react-beautiful-dnd": "^13.1.0", "react-transition-group": "^4.4.2", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "engines": { "node": ">=10" @@ -381,7 +381,7 @@ "@deephaven/log": "^0.58.0", "@deephaven/utils": "^0.58.0", "lodash.clamp": "^4.0.3", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "engines": { "node": ">=16" @@ -429,7 +429,7 @@ "@deephaven/log": "^0.58.0", "@deephaven/utils": "^0.58.0", "lodash.debounce": "^4.0.8", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "engines": { "node": ">=16" @@ -6898,15 +6898,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shortid": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", - "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dependencies": { - "nanoid": "^2.1.0" - } - }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -7478,7 +7469,7 @@ "react-transition-group": "^4.4.2", "react-virtualized-auto-sizer": "1.0.6", "react-window": "^1.8.6", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" } }, "@deephaven/console": { @@ -7507,7 +7498,7 @@ "popper.js": "^1.16.1", "prop-types": "^15.7.2", "shell-quote": "^1.7.2", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" } }, "@deephaven/dashboard": { @@ -7525,7 +7516,7 @@ "lodash.ismatch": "^4.1.1", "lodash.throttle": "^4.1.1", "prop-types": "^15.7.2", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" } }, "@deephaven/filters": { @@ -7597,7 +7588,7 @@ "prop-types": "^15.7.2", "react-beautiful-dnd": "^13.1.0", "react-transition-group": "^4.4.2", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" } }, "@deephaven/jsapi-bootstrap": { @@ -7626,7 +7617,7 @@ "@deephaven/log": "^0.58.0", "@deephaven/utils": "^0.58.0", "lodash.clamp": "^4.0.3", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" } }, "@deephaven/log": { @@ -7662,7 +7653,7 @@ "@deephaven/log": "^0.58.0", "@deephaven/utils": "^0.58.0", "lodash.debounce": "^4.0.8", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" } }, "@deephaven/redux": { @@ -12683,14 +12674,6 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==" }, - "shortid": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", - "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==", - "requires": { - "nanoid": "^2.1.0" - } - }, "side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", diff --git a/templates/widget/{{ cookiecutter.python_project_name }}/src/js/src/package-lock.json b/templates/widget/{{ cookiecutter.python_project_name }}/src/js/src/package-lock.json index 33d1c1aae..8d4b53f88 100644 --- a/templates/widget/{{ cookiecutter.python_project_name }}/src/js/src/package-lock.json +++ b/templates/widget/{{ cookiecutter.python_project_name }}/src/js/src/package-lock.json @@ -16,7 +16,7 @@ "@deephaven/jsapi-types": "^0.58.0", "@deephaven/log": "^0.58.0", "@deephaven/plugin": "^0.58.0", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "devDependencies": { "@deephaven/tsconfig": "^0.72.0", @@ -175,7 +175,7 @@ "react-transition-group": "^4.4.2", "react-virtualized-auto-sizer": "1.0.6", "react-window": "^1.8.6", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "engines": { "node": ">=10" @@ -211,7 +211,7 @@ "popper.js": "^1.16.1", "prop-types": "^15.7.2", "shell-quote": "^1.7.2", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "engines": { "node": ">=16" @@ -236,7 +236,7 @@ "lodash.ismatch": "^4.1.1", "lodash.throttle": "^4.1.1", "prop-types": "^15.7.2", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "engines": { "node": ">=16" @@ -334,7 +334,7 @@ "prop-types": "^15.7.2", "react-beautiful-dnd": "^13.1.0", "react-transition-group": "^4.4.2", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "engines": { "node": ">=10" @@ -379,7 +379,7 @@ "@deephaven/log": "^0.58.0", "@deephaven/utils": "^0.58.0", "lodash.clamp": "^4.0.3", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "engines": { "node": ">=16" @@ -427,7 +427,7 @@ "@deephaven/log": "^0.58.0", "@deephaven/utils": "^0.58.0", "lodash.debounce": "^4.0.8", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" }, "engines": { "node": ">=16" @@ -6896,15 +6896,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/shortid": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", - "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dependencies": { - "nanoid": "^2.1.0" - } - }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -7476,7 +7467,7 @@ "react-transition-group": "^4.4.2", "react-virtualized-auto-sizer": "1.0.6", "react-window": "^1.8.6", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" } }, "@deephaven/console": { @@ -7505,7 +7496,7 @@ "popper.js": "^1.16.1", "prop-types": "^15.7.2", "shell-quote": "^1.7.2", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" } }, "@deephaven/dashboard": { @@ -7523,7 +7514,7 @@ "lodash.ismatch": "^4.1.1", "lodash.throttle": "^4.1.1", "prop-types": "^15.7.2", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" } }, "@deephaven/filters": { @@ -7595,7 +7586,7 @@ "prop-types": "^15.7.2", "react-beautiful-dnd": "^13.1.0", "react-transition-group": "^4.4.2", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" } }, "@deephaven/jsapi-bootstrap": { @@ -7624,7 +7615,7 @@ "@deephaven/log": "^0.58.0", "@deephaven/utils": "^0.58.0", "lodash.clamp": "^4.0.3", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" } }, "@deephaven/log": { @@ -7660,7 +7651,7 @@ "@deephaven/log": "^0.58.0", "@deephaven/utils": "^0.58.0", "lodash.debounce": "^4.0.8", - "shortid": "^2.2.16" + "nanoid": "^5.0.7" } }, "@deephaven/redux": { @@ -12681,14 +12672,6 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==" }, - "shortid": { - "version": "2.2.16", - "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz", - "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==", - "requires": { - "nanoid": "^2.1.0" - } - }, "side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", diff --git a/tests/app.d/ui_render_all.py b/tests/app.d/ui_render_all.py index 3d138a3c5..1d82022f3 100644 --- a/tests/app.d/ui_render_all.py +++ b/tests/app.d/ui_render_all.py @@ -64,7 +64,11 @@ def ui_components(): ui.heading("Heading"), ui.icon("vsSymbolMisc"), # TODO: #526 ui.icon_wrapper("TODO: fix this"), - ui.illustrated_message(ui.icon("vsSymbolMisc"), "Illustrated Message"), + ui.illustrated_message( + ui.icon("vsWarning"), + ui.heading("Warning"), + ui.content("This is a warning message."), + ), ui.list_view( _item_table_source_with_action_group, aria_label="List View - List action group", diff --git a/tests/ui.spec.ts-snapshots/UI-all-components-render-1-chromium-linux.png b/tests/ui.spec.ts-snapshots/UI-all-components-render-1-chromium-linux.png index 497c29423..9cf9ed48f 100644 Binary files a/tests/ui.spec.ts-snapshots/UI-all-components-render-1-chromium-linux.png and b/tests/ui.spec.ts-snapshots/UI-all-components-render-1-chromium-linux.png differ diff --git a/tests/ui.spec.ts-snapshots/UI-all-components-render-1-firefox-linux.png b/tests/ui.spec.ts-snapshots/UI-all-components-render-1-firefox-linux.png index 84b32377c..a317fac6e 100644 Binary files a/tests/ui.spec.ts-snapshots/UI-all-components-render-1-firefox-linux.png and b/tests/ui.spec.ts-snapshots/UI-all-components-render-1-firefox-linux.png differ diff --git a/tests/ui.spec.ts-snapshots/UI-all-components-render-1-webkit-linux.png b/tests/ui.spec.ts-snapshots/UI-all-components-render-1-webkit-linux.png index 456fb28df..8c9f65732 100644 Binary files a/tests/ui.spec.ts-snapshots/UI-all-components-render-1-webkit-linux.png and b/tests/ui.spec.ts-snapshots/UI-all-components-render-1-webkit-linux.png differ