diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e0f877e70..a1f5305cee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,41 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Bug Fixes + +* Change display of rollup key columns from null to empty string ([#1563](https://github.com/deephaven/web-client-ui/issues/1563)) ([327bcb6](https://github.com/deephaven/web-client-ui/commit/327bcb649d47bff648a71fd7f979a63094650b25)), closes [#1483](https://github.com/deephaven/web-client-ui/issues/1483) +* Disabled failing e2e test ([#1554](https://github.com/deephaven/web-client-ui/issues/1554)) ([49723ec](https://github.com/deephaven/web-client-ui/commit/49723ec6669b6afb0c74f2c4e8d88862a64e0f06)), closes [#1553](https://github.com/deephaven/web-client-ui/issues/1553) +* Formatting Rule Doesn't use default set by user ([#1547](https://github.com/deephaven/web-client-ui/issues/1547)) ([ce51229](https://github.com/deephaven/web-client-ui/commit/ce51229231a9aae27871901412177e33dad24bea)) +* Handle deletion of unsaved copied file in NotebookPanel ([#1557](https://github.com/deephaven/web-client-ui/issues/1557)) ([4021aac](https://github.com/deephaven/web-client-ui/commit/4021aac3bc130f8eec84385c9aadcb4ecf0b995c)), closes [#1359](https://github.com/deephaven/web-client-ui/issues/1359) +* Prompt for resetting layout ([#1552](https://github.com/deephaven/web-client-ui/issues/1552)) ([a273e64](https://github.com/deephaven/web-client-ui/commit/a273e6433a81f5500fb39992cac276bcbdbda753)), closes [#1250](https://github.com/deephaven/web-client-ui/issues/1250) + + +* fix!: CSS based loading spinner (#1532) ([f06fbb0](https://github.com/deephaven/web-client-ui/commit/f06fbb01e27eaaeccab6031d8ff010ffee303d99)), closes [#1532](https://github.com/deephaven/web-client-ui/issues/1532) [#1531](https://github.com/deephaven/web-client-ui/issues/1531) + + +### Features + +* Add copy/rename/delete options to notebook overflow menu ([#1551](https://github.com/deephaven/web-client-ui/issues/1551)) ([4441109](https://github.com/deephaven/web-client-ui/commit/4441109d10dcee8a9415b6884114ee5083fd1cc0)), closes [#1359](https://github.com/deephaven/web-client-ui/issues/1359) +* data bar render from API ([#1415](https://github.com/deephaven/web-client-ui/issues/1415)) ([ee7d1c1](https://github.com/deephaven/web-client-ui/commit/ee7d1c108e86973b4c6855e482dce21d665dfe28)), closes [#0000](https://github.com/deephaven/web-client-ui/issues/0000) [#FF0000](https://github.com/deephaven/web-client-ui/issues/FF0000) [#FFFF00](https://github.com/deephaven/web-client-ui/issues/FFFF00) [#FFFF00](https://github.com/deephaven/web-client-ui/issues/FFFF00) [#00FF00](https://github.com/deephaven/web-client-ui/issues/00FF00) +* Monaco theming ([#1560](https://github.com/deephaven/web-client-ui/issues/1560)) ([4eda17c](https://github.com/deephaven/web-client-ui/commit/4eda17c82f6c177a11ba600d6f43c4f36915f6bd)), closes [#1542](https://github.com/deephaven/web-client-ui/issues/1542) +* Theme Plugin Loading ([#1524](https://github.com/deephaven/web-client-ui/issues/1524)) ([a9541b1](https://github.com/deephaven/web-client-ui/commit/a9541b108f1d998bb2713e70642f5a54aaf8bd97)), closes [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1530](https://github.com/deephaven/web-client-ui/issues/1530) + + +### BREAKING CHANGES + +* Theme variables have to be present on body to avoid +Monaco init failing +* Inline LoadingSpinner instances will need to be +decorated with `className="loading-spinner-vertical-align"` for vertical +alignment to work as before + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) diff --git a/lerna.json b/lerna.json index 6006f9ae2f..a99723cf66 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "useNx": false, - "version": "0.49.1", + "version": "0.50.0", "command": { "publish": { "distTag": "latest" diff --git a/package-lock.json b/package-lock.json index bcdc272adc..fac28af5cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,6 +85,7 @@ "@types/react": "^17.0.2", "@types/react-beautiful-dnd": "^13.1.2", "@types/react-dom": "^17.0.9", + "@types/react-is": "^17.0.2", "@types/react-plotly.js": "^2.6.0", "@types/react-router-dom": "^5.1.2", "@types/react-test-renderer": "^17.0.1", @@ -8724,6 +8725,15 @@ "@types/react": "*" } }, + "node_modules/@types/react-is": { + "version": "17.0.5", + "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.5.tgz", + "integrity": "sha512-mTTgVYfA8fLtyyuppoO7hQJWLV5TNivNKle5vBryoOwlA5158/4UgcZFOx59po/zC0K2ZBEv/IRATlxdVJRVQA==", + "dev": true, + "dependencies": { + "@types/react": "^17" + } + }, "node_modules/@types/react-plotly.js": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@types/react-plotly.js/-/react-plotly.js-2.6.0.tgz", @@ -27919,11 +27929,15 @@ }, "packages/app-utils": { "name": "@deephaven/app-utils", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { + "@adobe/react-spectrum": "^3.29.0", "@deephaven/auth-plugins": "file:../auth-plugins", + "@deephaven/chart": "file:../chart", "@deephaven/components": "file:../components", + "@deephaven/icons": "file:../icons", + "@deephaven/iris-grid": "file:../iris-grid", "@deephaven/jsapi-bootstrap": "file:../jsapi-bootstrap", "@deephaven/jsapi-components": "file:../jsapi-components", "@deephaven/jsapi-types": "file:../jsapi-types", @@ -27998,7 +28012,7 @@ }, "packages/auth-plugins": { "name": "@deephaven/auth-plugins", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/components": "file:../components", @@ -28026,7 +28040,7 @@ }, "packages/babel-preset": { "name": "@deephaven/babel-preset", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@babel/core": "^7.20.0", @@ -28041,7 +28055,7 @@ }, "packages/chart": { "name": "@deephaven/chart", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/icons": "file:../icons", @@ -28072,9 +28086,10 @@ }, "packages/code-studio": { "name": "@deephaven/code-studio", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { + "@adobe/react-spectrum": "^3.29.0", "@deephaven/app-utils": "file:../app-utils", "@deephaven/auth-plugins": "file:../auth-plugins", "@deephaven/chart": "file:../chart", @@ -28165,7 +28180,7 @@ }, "packages/components": { "name": "@deephaven/components", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@adobe/react-spectrum": "^3.29.0", @@ -28204,7 +28219,7 @@ }, "packages/console": { "name": "@deephaven/console", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/chart": "file:../chart", @@ -28244,7 +28259,7 @@ }, "packages/dashboard": { "name": "@deephaven/dashboard", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/components": "file:../components", @@ -28270,12 +28285,13 @@ "peerDependencies": { "react": "^17.0.0", "react-dom": "^17.0.0", + "react-is": "^17.0.0", "react-redux": "^7.2.4" } }, "packages/dashboard-core-plugins": { "name": "@deephaven/dashboard-core-plugins", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/app-utils": "file:../app-utils", @@ -28339,9 +28355,15 @@ "@types/lodash": "*" } }, + "packages/dashboard/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "peer": true + }, "packages/embed-chart": { "name": "@deephaven/embed-chart", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/app-utils": "file:../app-utils", @@ -28364,7 +28386,7 @@ }, "packages/embed-grid": { "name": "@deephaven/embed-grid", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/app-utils": "file:../app-utils", @@ -28387,7 +28409,7 @@ }, "packages/eslint-config": { "name": "@deephaven/eslint-config", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "eslint-config-airbnb": "^19.0.4", @@ -28406,7 +28428,7 @@ }, "packages/file-explorer": { "name": "@deephaven/file-explorer", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/components": "file:../components", @@ -28432,7 +28454,7 @@ }, "packages/filters": { "name": "@deephaven/filters", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "engines": { "node": ">=16" @@ -28440,7 +28462,7 @@ }, "packages/golden-layout": { "name": "@deephaven/golden-layout", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/components": "file:../components", @@ -28459,7 +28481,7 @@ }, "packages/grid": { "name": "@deephaven/grid", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/utils": "file:../utils", @@ -28481,7 +28503,7 @@ }, "packages/icons": { "name": "@deephaven/icons", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@fortawesome/fontawesome-common-types": "^6.1.1" @@ -28498,7 +28520,7 @@ }, "packages/iris-grid": { "name": "@deephaven/iris-grid", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/components": "file:../components", @@ -28543,7 +28565,7 @@ }, "packages/jsapi-bootstrap": { "name": "@deephaven/jsapi-bootstrap", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/components": "file:../components", @@ -28563,7 +28585,7 @@ }, "packages/jsapi-components": { "name": "@deephaven/jsapi-components", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/components": "file:../components", @@ -28592,7 +28614,7 @@ }, "packages/jsapi-shim": { "name": "@deephaven/jsapi-shim", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/jsapi-types": "file:../jsapi-types", @@ -28604,7 +28626,7 @@ }, "packages/jsapi-types": { "name": "@deephaven/jsapi-types", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "engines": { "node": ">=16" @@ -28612,7 +28634,7 @@ }, "packages/jsapi-utils": { "name": "@deephaven/jsapi-utils", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/filters": "file:../filters", @@ -28631,7 +28653,7 @@ }, "packages/log": { "name": "@deephaven/log", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "event-target-shim": "^6.0.2" @@ -28642,7 +28664,7 @@ }, "packages/mocks": { "name": "@deephaven/mocks", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "peerDependencies": { "jest": "29.x" @@ -28650,15 +28672,22 @@ }, "packages/plugin": { "name": "@deephaven/plugin", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/components": "file:../components", + "@deephaven/golden-layout": "file:../golden-layout", + "@deephaven/icons": "file:../icons", "@deephaven/iris-grid": "file:../iris-grid", - "@deephaven/jsapi-types": "file:../jsapi-types" + "@deephaven/jsapi-types": "file:../jsapi-types", + "@fortawesome/fontawesome-common-types": "^6.1.1", + "@fortawesome/react-fontawesome": "^0.2.0" }, "engines": { "node": ">=16" + }, + "peerDependencies": { + "react": "^17.x" } }, "packages/plugin-utils": { @@ -28691,7 +28720,7 @@ }, "packages/pouch-storage": { "name": "@deephaven/pouch-storage", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/console": "file:../console", @@ -28712,7 +28741,7 @@ }, "packages/prettier-config": { "name": "@deephaven/prettier-config", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "peerDependencies": { "prettier": "^3.0.0" @@ -28720,7 +28749,7 @@ }, "packages/react-hooks": { "name": "@deephaven/react-hooks", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@adobe/react-spectrum": "^3.29.0", @@ -28738,7 +28767,7 @@ }, "packages/redux": { "name": "@deephaven/redux", - "version": "0.49.1", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/jsapi-types": "file:../jsapi-types", @@ -28756,7 +28785,7 @@ }, "packages/storage": { "name": "@deephaven/storage", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "@deephaven/filters": "file:../filters", @@ -28772,7 +28801,7 @@ }, "packages/stylelint-config": { "name": "@deephaven/stylelint-config", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "dependencies": { "stylelint-config-prettier-scss": "^0.0.1", @@ -28784,13 +28813,13 @@ }, "packages/tsconfig": { "name": "@deephaven/tsconfig", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0" }, "packages/util": {}, "packages/utils": { "name": "@deephaven/utils", - "version": "0.49.0", + "version": "0.50.0", "license": "Apache-2.0", "engines": { "node": ">=16" @@ -30029,8 +30058,12 @@ "@deephaven/app-utils": { "version": "file:packages/app-utils", "requires": { + "@adobe/react-spectrum": "^3.29.0", "@deephaven/auth-plugins": "file:../auth-plugins", + "@deephaven/chart": "file:../chart", "@deephaven/components": "file:../components", + "@deephaven/icons": "file:../icons", + "@deephaven/iris-grid": "file:../iris-grid", "@deephaven/jsapi-bootstrap": "file:../jsapi-bootstrap", "@deephaven/jsapi-components": "file:../jsapi-components", "@deephaven/jsapi-types": "file:../jsapi-types", @@ -30103,6 +30136,7 @@ "@deephaven/code-studio": { "version": "file:packages/code-studio", "requires": { + "@adobe/react-spectrum": "^3.29.0", "@deephaven/app-utils": "file:../app-utils", "@deephaven/auth-plugins": "file:../auth-plugins", "@deephaven/chart": "file:../chart", @@ -30256,6 +30290,12 @@ "requires": { "@types/lodash": "*" } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "peer": true } } }, @@ -30499,8 +30539,12 @@ "version": "file:packages/plugin", "requires": { "@deephaven/components": "file:../components", + "@deephaven/golden-layout": "file:../golden-layout", + "@deephaven/icons": "file:../icons", "@deephaven/iris-grid": "file:../iris-grid", - "@deephaven/jsapi-types": "file:../jsapi-types" + "@deephaven/jsapi-types": "file:../jsapi-types", + "@fortawesome/fontawesome-common-types": "^6.1.1", + "@fortawesome/react-fontawesome": "^0.2.0" } }, "@deephaven/pouch-storage": { @@ -35494,6 +35538,15 @@ "@types/react": "*" } }, + "@types/react-is": { + "version": "17.0.5", + "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.5.tgz", + "integrity": "sha512-mTTgVYfA8fLtyyuppoO7hQJWLV5TNivNKle5vBryoOwlA5158/4UgcZFOx59po/zC0K2ZBEv/IRATlxdVJRVQA==", + "dev": true, + "requires": { + "@types/react": "^17" + } + }, "@types/react-plotly.js": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@types/react-plotly.js/-/react-plotly.js-2.6.0.tgz", diff --git a/package.json b/package.json index 4e41456ff5..edf80f7449 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "@types/react": "^17.0.2", "@types/react-beautiful-dnd": "^13.1.2", "@types/react-dom": "^17.0.9", + "@types/react-is": "^17.0.2", "@types/react-plotly.js": "^2.6.0", "@types/react-router-dom": "^5.1.2", "@types/react-test-renderer": "^17.0.1", diff --git a/packages/app-utils/CHANGELOG.md b/packages/app-utils/CHANGELOG.md index 162ae18ca9..3e756c5207 100644 --- a/packages/app-utils/CHANGELOG.md +++ b/packages/app-utils/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Features + +* Theme Plugin Loading ([#1524](https://github.com/deephaven/web-client-ui/issues/1524)) ([a9541b1](https://github.com/deephaven/web-client-ui/commit/a9541b108f1d998bb2713e70642f5a54aaf8bd97)), closes [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1530](https://github.com/deephaven/web-client-ui/issues/1530) + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) **Note:** Version bump only for package @deephaven/app-utils diff --git a/packages/app-utils/package.json b/packages/app-utils/package.json index 574f28bea5..9968aabfda 100644 --- a/packages/app-utils/package.json +++ b/packages/app-utils/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/app-utils", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven App Utils", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", @@ -28,8 +28,12 @@ "redux": "^4.x" }, "dependencies": { + "@adobe/react-spectrum": "^3.29.0", "@deephaven/auth-plugins": "file:../auth-plugins", + "@deephaven/chart": "file:../chart", "@deephaven/components": "file:../components", + "@deephaven/icons": "file:../icons", + "@deephaven/iris-grid": "file:../iris-grid", "@deephaven/jsapi-bootstrap": "file:../jsapi-bootstrap", "@deephaven/jsapi-components": "file:../jsapi-components", "@deephaven/jsapi-types": "file:../jsapi-types", diff --git a/packages/app-utils/src/components/AppBootstrap.tsx b/packages/app-utils/src/components/AppBootstrap.tsx index 00d3f59368..d0305d0125 100644 --- a/packages/app-utils/src/components/AppBootstrap.tsx +++ b/packages/app-utils/src/components/AppBootstrap.tsx @@ -5,7 +5,7 @@ import { RefreshTokenBootstrap, useBroadcastLoginListener, } from '@deephaven/jsapi-components'; -import { type DashboardPlugin } from '@deephaven/plugin'; +import { type Plugin } from '@deephaven/plugin'; import FontBootstrap from './FontBootstrap'; import PluginsBootstrap from './PluginsBootstrap'; import AuthBootstrap from './AuthBootstrap'; @@ -24,7 +24,7 @@ export type AppBootstrapProps = { pluginsUrl: string; /** The core plugins to load. */ - getCorePlugins?: () => Promise; + getCorePlugins?: () => Promise; /** Font class names to load. */ fontClassNames?: string[]; diff --git a/packages/app-utils/src/components/PluginsBootstrap.tsx b/packages/app-utils/src/components/PluginsBootstrap.tsx index a60dfd3966..5fdea74c82 100644 --- a/packages/app-utils/src/components/PluginsBootstrap.tsx +++ b/packages/app-utils/src/components/PluginsBootstrap.tsx @@ -1,4 +1,4 @@ -import { type DashboardPlugin } from '@deephaven/plugin'; +import { type Plugin } from '@deephaven/plugin'; import React, { createContext, useEffect, useState } from 'react'; import { PluginModuleMap, loadModulePlugins } from '../plugins'; @@ -11,7 +11,7 @@ export type PluginsBootstrapProps = { pluginsUrl: string; /** The core plugins to load. */ - getCorePlugins?: () => Promise; + getCorePlugins?: () => Promise; /** * The children to render wrapped with the PluginsContext. diff --git a/packages/app-utils/src/plugins/remote-component.config.ts b/packages/app-utils/src/plugins/remote-component.config.ts index 26b79e289c..21dfe9f21f 100644 --- a/packages/app-utils/src/plugins/remote-component.config.ts +++ b/packages/app-utils/src/plugins/remote-component.config.ts @@ -8,12 +8,16 @@ import react from 'react'; import * as redux from 'redux'; import * as reactRedux from 'react-redux'; import ReactDOM from 'react-dom'; +import * as AdobeReactSpectrum from '@adobe/react-spectrum'; import * as DeephavenAuthPlugins from '@deephaven/auth-plugins'; +import * as DeephavenChart from '@deephaven/chart'; import * as DeephavenComponents from '@deephaven/components'; +import * as DeephavenIcons from '@deephaven/icons'; +import * as DeephavenIrisGrid from '@deephaven/iris-grid'; import * as DeephavenJsapiBootstrap from '@deephaven/jsapi-bootstrap'; import * as DeephavenJsapiComponents from '@deephaven/jsapi-components'; import * as DeephavenJsapiUtils from '@deephaven/jsapi-utils'; -import * as DeephavenLog from '@deephaven/log'; +import DeephavenLog from '@deephaven/log'; import * as DeephavenReactHooks from '@deephaven/react-hooks'; // eslint-disable-next-line import/prefer-default-export @@ -22,8 +26,12 @@ export const resolve = { 'react-dom': ReactDOM, redux, 'react-redux': reactRedux, + '@adobe/react-spectrum': AdobeReactSpectrum, '@deephaven/auth-plugins': DeephavenAuthPlugins, + '@deephaven/chart': DeephavenChart, '@deephaven/components': DeephavenComponents, + '@deephaven/icons': DeephavenIcons, + '@deephaven/iris-grid': DeephavenIrisGrid, '@deephaven/jsapi-bootstrap': DeephavenJsapiBootstrap, '@deephaven/jsapi-components': DeephavenJsapiComponents, '@deephaven/jsapi-utils': DeephavenJsapiUtils, diff --git a/packages/app-utils/tsconfig.json b/packages/app-utils/tsconfig.json index f18e274171..f5e6f5ea9b 100644 --- a/packages/app-utils/tsconfig.json +++ b/packages/app-utils/tsconfig.json @@ -8,7 +8,9 @@ "exclude": ["node_modules", "src/**/*.test.*", "src/**/__mocks__/*"], "references": [ { "path": "../auth-plugins" }, + { "path": "../chart" }, { "path": "../components" }, + { "path": "../iris-grid" }, { "path": "../jsapi-bootstrap" }, { "path": "../jsapi-components" }, { "path": "../jsapi-types" }, diff --git a/packages/auth-plugins/CHANGELOG.md b/packages/auth-plugins/CHANGELOG.md index 4a7a096317..bf1f1e8bf8 100644 --- a/packages/auth-plugins/CHANGELOG.md +++ b/packages/auth-plugins/CHANGELOG.md @@ -3,6 +3,22 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +* fix!: CSS based loading spinner (#1532) ([f06fbb0](https://github.com/deephaven/web-client-ui/commit/f06fbb01e27eaaeccab6031d8ff010ffee303d99)), closes [#1532](https://github.com/deephaven/web-client-ui/issues/1532) [#1531](https://github.com/deephaven/web-client-ui/issues/1531) + + +### BREAKING CHANGES + +* Inline LoadingSpinner instances will need to be +decorated with `className="loading-spinner-vertical-align"` for vertical +alignment to work as before + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) **Note:** Version bump only for package @deephaven/auth-plugins diff --git a/packages/auth-plugins/package.json b/packages/auth-plugins/package.json index f0d5186ca7..57e75cbe25 100644 --- a/packages/auth-plugins/package.json +++ b/packages/auth-plugins/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/auth-plugins", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven Auth Plugins", "keywords": [ "Deephaven", diff --git a/packages/babel-preset/CHANGELOG.md b/packages/babel-preset/CHANGELOG.md index 5a9c51cae0..ae46a12db8 100644 --- a/packages/babel-preset/CHANGELOG.md +++ b/packages/babel-preset/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Features + +* Theme Plugin Loading ([#1524](https://github.com/deephaven/web-client-ui/issues/1524)) ([a9541b1](https://github.com/deephaven/web-client-ui/commit/a9541b108f1d998bb2713e70642f5a54aaf8bd97)), closes [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1530](https://github.com/deephaven/web-client-ui/issues/1530) + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/babel-preset diff --git a/packages/babel-preset/package.json b/packages/babel-preset/package.json index 1a97da6f66..8f6b5ad9e0 100644 --- a/packages/babel-preset/package.json +++ b/packages/babel-preset/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/babel-preset", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven Babel preset", "repository": { "type": "git", diff --git a/packages/chart/CHANGELOG.md b/packages/chart/CHANGELOG.md index 696b6c72d7..cc8338011f 100644 --- a/packages/chart/CHANGELOG.md +++ b/packages/chart/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/chart + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/chart diff --git a/packages/chart/package.json b/packages/chart/package.json index b402af83e9..1b70fab042 100644 --- a/packages/chart/package.json +++ b/packages/chart/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/chart", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven Chart", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/chart/src/Chart.tsx b/packages/chart/src/Chart.tsx index c05a48ccaf..67220688d0 100644 --- a/packages/chart/src/Chart.tsx +++ b/packages/chart/src/Chart.tsx @@ -166,27 +166,33 @@ export class Chart extends Component { this.initData(); this.initFormatter(); - const { isActive } = this.props; + const { isActive, model } = this.props; if (isActive) { - this.subscribe(); + this.subscribe(model); } } componentDidUpdate(prevProps: ChartProps): void { - const { isActive, settings } = this.props; + const { isActive, model, settings } = this.props; this.updateFormatterSettings(settings as FormatterSettings); + if (model !== prevProps.model) { + this.unsubscribe(prevProps.model); + this.subscribe(model); + } + if (isActive !== prevProps.isActive) { if (isActive) { - this.subscribe(); + this.subscribe(model); } else { - this.unsubscribe(); + this.unsubscribe(model); } } } componentWillUnmount(): void { - this.unsubscribe(); + const { model } = this.props; + this.unsubscribe(model); } currentSeries: number; @@ -315,12 +321,11 @@ export class Chart extends Component { }); } - subscribe(): void { + subscribe(model: ChartModel): void { if (this.isSubscribed) { return; } - const { model } = this.props; if (!this.rect || this.rect.width === 0 || this.rect.height === 0) { log.debug2('Delaying subscription until model dimensions are set'); return; @@ -329,12 +334,11 @@ export class Chart extends Component { this.isSubscribed = true; } - unsubscribe(): void { + unsubscribe(model: ChartModel): void { if (!this.isSubscribed) { return; } - const { model } = this.props; model.unsubscribe(this.handleModelEvent); this.isSubscribed = false; } @@ -510,7 +514,7 @@ export class Chart extends Component { model.setDimensions(rect); // We may need to resubscribe if dimensions were too small before if (isActive) { - this.subscribe(); + this.subscribe(model); } } } diff --git a/packages/code-studio/CHANGELOG.md b/packages/code-studio/CHANGELOG.md index 319aeba647..4368d26e82 100644 --- a/packages/code-studio/CHANGELOG.md +++ b/packages/code-studio/CHANGELOG.md @@ -3,6 +3,37 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Bug Fixes + +* Formatting Rule Doesn't use default set by user ([#1547](https://github.com/deephaven/web-client-ui/issues/1547)) ([ce51229](https://github.com/deephaven/web-client-ui/commit/ce51229231a9aae27871901412177e33dad24bea)) +* Prompt for resetting layout ([#1552](https://github.com/deephaven/web-client-ui/issues/1552)) ([a273e64](https://github.com/deephaven/web-client-ui/commit/a273e6433a81f5500fb39992cac276bcbdbda753)), closes [#1250](https://github.com/deephaven/web-client-ui/issues/1250) + + +* fix!: CSS based loading spinner (#1532) ([f06fbb0](https://github.com/deephaven/web-client-ui/commit/f06fbb01e27eaaeccab6031d8ff010ffee303d99)), closes [#1532](https://github.com/deephaven/web-client-ui/issues/1532) [#1531](https://github.com/deephaven/web-client-ui/issues/1531) + + +### Features + +* data bar render from API ([#1415](https://github.com/deephaven/web-client-ui/issues/1415)) ([ee7d1c1](https://github.com/deephaven/web-client-ui/commit/ee7d1c108e86973b4c6855e482dce21d665dfe28)), closes [#0000](https://github.com/deephaven/web-client-ui/issues/0000) [#FF0000](https://github.com/deephaven/web-client-ui/issues/FF0000) [#FFFF00](https://github.com/deephaven/web-client-ui/issues/FFFF00) [#FFFF00](https://github.com/deephaven/web-client-ui/issues/FFFF00) [#00FF00](https://github.com/deephaven/web-client-ui/issues/00FF00) +* Monaco theming ([#1560](https://github.com/deephaven/web-client-ui/issues/1560)) ([4eda17c](https://github.com/deephaven/web-client-ui/commit/4eda17c82f6c177a11ba600d6f43c4f36915f6bd)), closes [#1542](https://github.com/deephaven/web-client-ui/issues/1542) +* Theme Plugin Loading ([#1524](https://github.com/deephaven/web-client-ui/issues/1524)) ([a9541b1](https://github.com/deephaven/web-client-ui/commit/a9541b108f1d998bb2713e70642f5a54aaf8bd97)), closes [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1530](https://github.com/deephaven/web-client-ui/issues/1530) + + +### BREAKING CHANGES + +* Theme variables have to be present on body to avoid +Monaco init failing +* Inline LoadingSpinner instances will need to be +decorated with `className="loading-spinner-vertical-align"` for vertical +alignment to work as before + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) **Note:** Version bump only for package @deephaven/code-studio diff --git a/packages/code-studio/package.json b/packages/code-studio/package.json index 4d456aa4f8..d7d555812f 100644 --- a/packages/code-studio/package.json +++ b/packages/code-studio/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/code-studio", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven Code Studio", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", @@ -11,6 +11,7 @@ "directory": "packages/code-studio" }, "dependencies": { + "@adobe/react-spectrum": "^3.29.0", "@deephaven/app-utils": "file:../app-utils", "@deephaven/auth-plugins": "file:../auth-plugins", "@deephaven/chart": "file:../chart", diff --git a/packages/code-studio/src/index.tsx b/packages/code-studio/src/index.tsx index 9205d0efac..5daf81ceb7 100644 --- a/packages/code-studio/src/index.tsx +++ b/packages/code-studio/src/index.tsx @@ -42,6 +42,7 @@ async function getCorePlugins() { FilterPluginConfig, MarkdownPluginConfig, LinkerPluginConfig, + WidgetLoaderPluginConfig, } = dashboardCorePlugins; return [ GridPluginConfig, @@ -51,6 +52,7 @@ async function getCorePlugins() { FilterPluginConfig, MarkdownPluginConfig, LinkerPluginConfig, + WidgetLoaderPluginConfig, ]; } diff --git a/packages/code-studio/src/styleguide/Colors.tsx b/packages/code-studio/src/styleguide/Colors.tsx index d84a1b0375..b796222817 100644 --- a/packages/code-studio/src/styleguide/Colors.tsx +++ b/packages/code-studio/src/styleguide/Colors.tsx @@ -3,22 +3,28 @@ import classNames from 'classnames'; function Colors(): React.ReactElement { const graySwatches = [ - '100', - '200', - '300', - '400', - '500', - '600', - '700', - '800', - '900', - ].map(swatch => ( + ['100', '900'], + ['200', '800'], + ['300', '700'], + ['400', '600'], + ['500', '500'], + ['600', '500'], + ['700', '400'], + ['800', '300'], + ['850', '200'], + ['900', '75'], + ].map(([swatch, dh]) => (
- Gray- - {swatch} + + Gray- + {swatch} + + + --dh-gray-{dh} +
)); diff --git a/packages/code-studio/src/styleguide/StyleGuide.scss b/packages/code-studio/src/styleguide/StyleGuide.scss index a7a2b654e5..58d270d8e2 100644 --- a/packages/code-studio/src/styleguide/StyleGuide.scss +++ b/packages/code-studio/src/styleguide/StyleGuide.scss @@ -18,6 +18,13 @@ pre { line-height: 2.5rem; } +.gray-swatch { + display: flex; + span { + flex: 1 0 50%; + } +} + .swatch-content-bg { border: 1px solid $gray-600; margin-top: 2.5rem; diff --git a/packages/code-studio/src/styleguide/StyleGuide.tsx b/packages/code-studio/src/styleguide/StyleGuide.tsx index bbfd8036e8..a71843a61c 100644 --- a/packages/code-studio/src/styleguide/StyleGuide.tsx +++ b/packages/code-studio/src/styleguide/StyleGuide.tsx @@ -21,6 +21,7 @@ import Typograpy from './Typography'; import './StyleGuide.scss'; import DraggableLists from './DraggableLists'; import Navigations from './Navigations'; +import ThemeColors from './ThemeColors'; function StyleGuide(): React.ReactElement { return ( @@ -33,6 +34,8 @@ function StyleGuide(): React.ReactElement { + + diff --git a/packages/code-studio/src/styleguide/ThemeColors.module.scss b/packages/code-studio/src/styleguide/ThemeColors.module.scss new file mode 100644 index 0000000000..2f65e1f9e5 --- /dev/null +++ b/packages/code-studio/src/styleguide/ThemeColors.module.scss @@ -0,0 +1,35 @@ +.themeColors { + --swatch-height: 35px; + --column-gap: 14px; + + display: grid; + column-gap: var(--column-gap); + // Add as many columns as will fit in the container each 210px wide. + // Row height is set to the swatch height (35px) by dynamic `grid-row` style + // attributes set in ThemeColors.tsx. + grid-template-columns: repeat(auto-fit, 210px); + + .label { + display: flex; + align-items: end; + justify-content: space-between; + gap: 4px; + height: var(--swatch-height); + text-transform: capitalize; + white-space: nowrap; + } + + .swatch { + display: flex; + align-items: center; + height: var(--swatch-height); + justify-content: space-between; + padding: 0 10px; + + span { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + } + } +} diff --git a/packages/code-studio/src/styleguide/ThemeColors.tsx b/packages/code-studio/src/styleguide/ThemeColors.tsx new file mode 100644 index 0000000000..07e2ca95ad --- /dev/null +++ b/packages/code-studio/src/styleguide/ThemeColors.tsx @@ -0,0 +1,178 @@ +import React, { useMemo } from 'react'; +import { Tooltip } from '@deephaven/components'; +import { ColorUtils } from '@deephaven/utils'; +import palette from '@deephaven/components/src/theme/theme-dark/theme-dark-palette.css?inline'; +import semantic from '@deephaven/components/src/theme/theme-dark/theme-dark-semantic.css?inline'; +import semanticEditor from '@deephaven/components/src/theme/theme-dark/theme-dark-semantic-editor.css?inline'; +import semanticGrid from '@deephaven/components/src/theme/theme-dark/theme-dark-semantic-grid.css?inline'; +import styles from './ThemeColors.module.scss'; + +// Group names are extracted from var names via a regex capture group. Most of +// them work pretty well, but some need to be remapped to a more appropriate +// group. +const reassignVarGroups: Record = { + '--dh-color-black': 'gray', + '--dh-color-white': 'gray', + // Editor + '--dh-color-editor-bg': 'editor', + '--dh-color-editor-fg': 'editor', + '--dh-color-editor-context-menu-bg': 'menus', + '--dh-color-editor-context-menu-fg': 'menus', + '--dh-color-editor-menu-selection-bg': 'menus', + // Grid + '--dh-color-grid-bg': 'grid', + '--dh-color-grid-number-positive': 'Data Types', + '--dh-color-grid-number-negative': 'Data Types', + '--dh-color-grid-number-zero': 'Data Types', + '--dh-color-grid-date': 'Data Types', + '--dh-color-grid-string-null': 'Data Types', +}; + +// Mappings of variable groups to rename +const renameGroups = { + editor: { + line: 'editor', + comment: 'code', + string: 'code', + number: 'code', + delimiter: 'code', + identifier: 'code', + keyword: 'code', + operator: 'code', + storage: 'code', + predefined: 'code', + selection: 'state', + focus: 'state', + }, + grid: { data: 'Data Bars', context: 'Context Menu' }, +}; + +export function ThemeColors(): JSX.Element { + const swatchDataGroups = useMemo( + () => ({ + 'Theme Color Palette': buildColorGroups(palette, 1), + 'Semantic Colors': buildColorGroups(semantic, 1), + 'Editor Colors': buildColorGroups(semanticEditor, 2, renameGroups.editor), + 'Grid Colors': buildColorGroups(semanticGrid, 2, renameGroups.grid), + }), + [] + ); + + return ( + <> + {Object.entries(swatchDataGroups).map(([label, data]) => ( +
+

{label}

+
+ {Object.entries(data).map(([group, swatchData]) => ( +
+ {group} + {swatchData.map(({ name, value }) => ( +
+ +
{name}
+
{value}
+
+ {ColorUtils.normalizeCssColor(value).replace( + /^(#[a-f0-9]{6})ff$/, + '$1' + )} +
+
+ {name.replace('--dh-color-', '')} + {name.endsWith('-hue') ? {value} : null} +
+ ))} +
+ ))} +
+
+ ))} + + ); +} + +export default ThemeColors; + +/** Return black or white contrast color */ +function contrastColor(color: string): 'black' | 'white' { + const rgba = ColorUtils.parseRgba(ColorUtils.asRgbOrRgbaString(color) ?? ''); + if (rgba == null || rgba.a < 0.5) { + return 'white'; + } + + const { r, g, b } = rgba; + const y = (299 * r + 587 * g + 114 * b) / 1000; + return y >= 128 ? 'black' : 'white'; +} + +/** Extract an array of { name, value } pairs for css variables in a given string */ +function extractColorVars( + styleText: string +): { name: string; value: string }[] { + const computedStyle = getComputedStyle(document.documentElement); + + return styleText + .split('\n') + .map(line => /^\s{2}(--dh-color-(?:[^:]+))/.exec(line)?.[1]) + .filter(Boolean) + .map(varName => + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + ({ name: varName!, value: computedStyle.getPropertyValue(varName!)! }) + ); +} + +/** Group color data based on capture group value */ +function buildColorGroups( + styleText: string, + captureGroupI: number, + groupRemap: Record = {} +): Record { + const swatchData = extractColorVars(styleText); + + const groupData = swatchData.reduce( + (acc, { name, value }) => { + const match = /^--dh-color-([^-]+)(?:-([^-]+))?/.exec(name); + let group = + reassignVarGroups[name] ?? + match?.[captureGroupI] ?? + match?.[1] ?? + '???'; + + group = groupRemap[group] ?? group; + + if (acc[group] == null) { + acc[group] = []; + } + + // Add a spacer for black / white + if (name === '--dh-color-black') { + acc[group].push({ name: '', value: '' }); + } + + acc[group].push({ name, value }); + + return acc; + }, + {} as Record + ); + + return groupData; +} diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 7e2afa8e4c..6a8610e74c 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +* fix!: CSS based loading spinner (#1532) ([f06fbb0](https://github.com/deephaven/web-client-ui/commit/f06fbb01e27eaaeccab6031d8ff010ffee303d99)), closes [#1532](https://github.com/deephaven/web-client-ui/issues/1532) [#1531](https://github.com/deephaven/web-client-ui/issues/1531) + + +### Features + +* Monaco theming ([#1560](https://github.com/deephaven/web-client-ui/issues/1560)) ([4eda17c](https://github.com/deephaven/web-client-ui/commit/4eda17c82f6c177a11ba600d6f43c4f36915f6bd)), closes [#1542](https://github.com/deephaven/web-client-ui/issues/1542) +* Theme Plugin Loading ([#1524](https://github.com/deephaven/web-client-ui/issues/1524)) ([a9541b1](https://github.com/deephaven/web-client-ui/commit/a9541b108f1d998bb2713e70642f5a54aaf8bd97)), closes [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1530](https://github.com/deephaven/web-client-ui/issues/1530) + + +### BREAKING CHANGES + +* Theme variables have to be present on body to avoid +Monaco init failing +* Inline LoadingSpinner instances will need to be +decorated with `className="loading-spinner-vertical-align"` for vertical +alignment to work as before + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) diff --git a/packages/components/package.json b/packages/components/package.json index 8019bf2060..bef23df3f2 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/components", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven React component library", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/components/src/theme/index.ts b/packages/components/src/theme/index.ts index 42d06c3079..873ca8f528 100644 --- a/packages/components/src/theme/index.ts +++ b/packages/components/src/theme/index.ts @@ -1,3 +1,5 @@ +export * from './theme-dark'; +export * from './theme-light'; export * from './ThemeModel'; export * from './ThemeProvider'; export * from './ThemeUtils'; diff --git a/packages/components/src/theme/theme-dark/theme-dark-palette.css b/packages/components/src/theme/theme-dark/theme-dark-palette.css index e5c60aa08e..61e2929c0c 100644 --- a/packages/components/src/theme/theme-dark/theme-dark-palette.css +++ b/packages/components/src/theme/theme-dark/theme-dark-palette.css @@ -3,7 +3,7 @@ --dh-color-gray-hue: 0deg; --dh-color-gray-50: hsl(var(--dh-color-gray-hue) 6% 10%); --dh-color-gray-75: hsl(var(--dh-color-gray-hue) 5% 13%); - --dh-color-gray-100: hsl(var(--dh-color-gray-hue), 5%, 17%); + --dh-color-gray-100: hsl(var(--dh-color-gray-hue) 5% 17%); --dh-color-gray-200: hsl(var(--dh-color-gray-hue) 4% 19%); --dh-color-gray-300: hsl(var(--dh-color-gray-hue) 4% 21%); --dh-color-gray-400: hsl(var(--dh-color-gray-hue) 2% 25%); diff --git a/packages/components/src/theme/theme-dark/theme-dark-semantic-editor.css b/packages/components/src/theme/theme-dark/theme-dark-semantic-editor.css index 41ee75dcc5..3366c97fe0 100644 --- a/packages/components/src/theme/theme-dark/theme-dark-semantic-editor.css +++ b/packages/components/src/theme/theme-dark/theme-dark-semantic-editor.css @@ -1,37 +1,37 @@ :root { /* Editor */ - --dh-color-editor-background: var(--dh-color-content-background); - --dh-color-editor-foreground: var(--dh-color-gray-900); - --dh-color-editor-error-foreground: var(--dh-color-visual-red); - --dh-color-editor-line-number-foreground: var(--dh-color-gray-700); + --dh-color-editor-bg: var(--dh-color-content-background); + --dh-color-editor-fg: var(--dh-color-gray-900); + --dh-color-editor-error-fg: var(--dh-color-visual-red); + --dh-color-editor-line-number-fg: var(--dh-color-gray-700); --dh-color-editor-line-highlight-bg: var(--dh-color-gray-200); - --dh-color-editor-selection-background: var(--dh-color-text-highlight); + --dh-color-editor-selection-bg: var(--dh-color-text-highlight); /* Code rules */ - --dh-color-editor-string: var(--dh-color-visual-yellow); - --dh-color-editor-string-delim: var(--dh-color-gray-700); + --dh-color-editor-comment: var(--dh-color-gray-700); --dh-color-editor-delimiter: var(--dh-color-gray-700); - --dh-color-editor-predefined: var(--dh-color-visual-green); + --dh-color-editor-identifier-js: var(--dh-color-visual-yellow); + --dh-color-editor-identifier-namespace: var(--dh-color-visual-red); + --dh-color-editor-identifier: var(--dh-color-gray-900); --dh-color-editor-keyword: var(--dh-color-visual-cyan); - --dh-color-editor-storage: var(--dh-color-visual-red); --dh-color-editor-number: var(--dh-color-visual-purple); --dh-color-editor-operator: var(--dh-color-visual-red); - --dh-color-editor-identifier: var(--dh-color-gray-900); - --dh-color-editor-identifier-namespace: var(--dh-color-visual-red); - --dh-color-editor-identifier-js: var(--dh-color-visual-yellow); - --dh-color-editor-comment: var(--dh-color-gray-700); + --dh-color-editor-predefined: var(--dh-color-visual-green); + --dh-color-editor-storage: var(--dh-color-visual-red); + --dh-color-editor-string-delim: var(--dh-color-gray-700); + --dh-color-editor-string: var(--dh-color-visual-yellow); /* Input */ --dh-color-editor-focus-border: var(--dh-color-focus-border); --dh-color-editor-input-option-active-border: var(--dh-color-focus-ring); - --dh-color-editor-input-background: var(--dh-color-background); - --dh-color-editor-input-foreground: var(--dh-color-text); + --dh-color-editor-input-bg: var(--dh-color-background); + --dh-color-editor-input-fg: var(--dh-color-text); --dh-color-editor-input-border: var(--dh-color-border); /* Menus */ - --dh-color-editor-context-menu-background: var(--dh-color-gray-300); - --dh-color-editor-context-menu-foreground: var(--dh-color-gray-900); - --dh-color-editor-menu-selection-background: var(--dh-color-highlight-hover); + --dh-color-editor-context-menu-bg: var(--dh-color-gray-300); + --dh-color-editor-context-menu-fg: var(--dh-color-gray-900); + --dh-color-editor-menu-selection-bg: var(--dh-color-highlight-hover); /* Logging */ --dh-color-editor-log-date: var(--dh-color-gray-700); @@ -43,25 +43,23 @@ --dh-color-editor-log-trace: var(--dh-color-visual-green); /* Find */ - --dh-color-editor-find-background: var(--dh-color-gray-200); - --dh-color-editor-find-match-background: var(--dh-color-highlight-selected); - --dh-color-editor-find-match-highlight-background: var( + --dh-color-editor-find-bg: var(--dh-color-gray-200); + --dh-color-editor-find-match-bg: var(--dh-color-highlight-selected); + --dh-color-editor-find-match-highlight-bg: var( --dh-color-highlight-selected-hover ); - --dh-color-editor-find-option-active-background: var(--dh-color-accent-700); - --dh-color-editor-find-option-active-foreground: var(--dh-color-gray-900); + --dh-color-editor-find-option-active-bg: var(--dh-color-accent-700); + --dh-color-editor-find-option-active-fg: var(--dh-color-gray-900); /* Suggest */ - --dh-color-editor-suggest-background: var(--dh-color-gray-200); + --dh-color-editor-suggest-bg: var(--dh-color-gray-200); --dh-color-editor-suggest-border: var(--dh-color-gray-400); - --dh-color-editor-suggest-foreground: var(--dh-color-gray-100); - --dh-color-editor-suggest-selected-background: var( - --dh-color-highlight-selected - ); - --dh-color-editor-suggest-highlight-foreground: var(--dh-color-accent-700); - --dh-color-editor-suggest-hover-background: var(--dh-color-highlight-hover); + --dh-color-editor-suggest-fg: var(--dh-color-gray-100); + --dh-color-editor-suggest-selected-bg: var(--dh-color-highlight-selected); + --dh-color-editor-suggest-highlight-fg: var(--dh-color-accent-700); + --dh-color-editor-suggest-hover-bg: var(--dh-color-highlight-hover); /* Links */ --dh-color-editor-link-foreground: var(--dh-color-accent-1000); - --dh-color-editor-link-active-foreground: var(--dh-color-accent-1100); + --dh-color-editor-link-active-fg: var(--dh-color-accent-1100); } diff --git a/packages/components/src/theme/theme-dark/theme-dark-semantic-grid.css b/packages/components/src/theme/theme-dark/theme-dark-semantic-grid.css index 20cdf034de..07922f8ba3 100644 --- a/packages/components/src/theme/theme-dark/theme-dark-semantic-grid.css +++ b/packages/components/src/theme/theme-dark/theme-dark-semantic-grid.css @@ -1,3 +1,96 @@ :root { - --dh-color-grid-background: var(--dh-color-background); + /* Grid */ + --dh-color-grid-bg: var(--dh-color-background); + + /* Header */ + --dh-color-grid-header-bg: var(--dh-color-gray-100); + --dh-color-grid-header-text: var(--dh-color-heading-text); + --dh-color-grid-header-separator: var(--dh-color-gray-50); + --dh-color-grid-header-separator-hover: var(--dh-color-gray-600); + --dh-color-grid-header-separator-hidden-hover: var(--dh-color-accent-700); + --dh-color-grid-header-sort-bar: var(--dh-color-visual-purple); + --dh-color-grid-header-reverse-bar: var(--dh-color-visual-green); + --dh-color-grid-header-bar-casing: var(--dh-color-gray-50); + + /* Row */ + --dh-color-grid-row-0-bg: var(--dh-color-gray-200); + --dh-color-grid-row-1-bg: var(--dh-color-gray-100); + --dh-color-grid-row-hover-bg: var(--dh-color-highlight-hover); + --dh-color-grid-row-hover-bg-selected: var( + --dh-color-highlight-selected-hover + ); + + /* Selection */ + --dh-color-grid-selection: var(--dh-color-highlight-selected); + --dh-color-grid-selection-outline: var(--dh-color-accent-900); + --dh-color-grid-selection-outline-casing: var(--dh-gray-50); + + /** Sroll Bar */ + --dh-color-grid-scroll-bar-active-selection-tick: var(--dh-color-accent-400); + --dh-color-grid-scroll-bar-bg: var(--dh-color-gray-100); + --dh-color-grid-scroll-bar-hover-bg: var(--dh-color-gray-200); + --dh-color-grid-scroll-bar-casing: var(--dh-color-gray-400); + --dh-color-grid-scroll-bar-corner: var(--dh-color-gray-100); + --dh-color-grid-scroll-bar: var(--dh-color-gray-500); + --dh-color-grid-scroll-bar-hover: var(--dh-color-gray-600); + --dh-color-grid-scroll-bar-active: var(--dh-color-gray-700); + + /* Text */ + --dh-color-grid-text: var(--dh-color-text); + --dh-color-grid-text-hyperlink: var(--dh-color-accent-1000); + --dh-color-grid-text-pending: var(--dh-color-yellow-1300); + --dh-color-grid-text-error: var(--dh-color-visual-negative); + + /* Data Types */ + --dh-color-grid-date: var(--dh-color-visual-notice); + --dh-color-grid-number-positive: var(--dh-color-visual-positive); + --dh-color-grid-number-negative: var(--dh-color-visual-negative); + --dh-color-grid-number-zero: var(--dh-color-visual-notice); + --dh-color-grid-string-null: var(--dh-color-gray-600); + + /* Filter Bar */ + --dh-color-grid-filter-bar-active-bg: var(--dh-color-accent-300); + --dh-color-grid-filter-bar-active: var(--dh-color-accent-600); + --dh-color-grid-filter-bar-expanded-bg: var(--dh-color-gray-200); + --dh-color-grid-filter-bar-expanded-active-bg: var(--dh-color-accent-100); + --dh-color-grid-filter-bar-expanded-active-cell-bg: var( + --dh-color-accent-200 + ); + --dh-color-grid-filter-bar-separator: var(--dh-color-gray-600); + --dh-color-grid-filter-bar-error: var(--dh-color-visual-negative); + --dh-color-grid-filter-icon: var(--dh-color-accent-600); + + /* Context Menu */ + --dh-color-grid-context-menu-sort-icon: var(--dh-color-visual-purple); + --dh-color-grid-context-menu-reverse-icon: var(--dh-color-visual-green); + + /* Column */ + --dh-color-grid-column-linker-hover-bg: var( + --dh-color-highlight-selected-hover + ); + --dh-color-grid-column-grouped-divider: var(--dh-color-gray-50); + + /* Tree */ + --dh-color-grid-tree-line: var(--dh-color-gray-500); + --dh-color-grid-tree-marker: var(--dh-color-gray-700); + --dh-color-grid-tree-marker-hover: var(--dh-color-gray-900); + + /* Floating */ + --dh-color-grid-floating-row: var(--dh-color-gray-300); + --dh-color-grid-floating-row-bg: var(--dh-color-gray-200); + --dh-color-grid-floating-divider-inner: var(--dh-color-gray-200); + --dh-color-grid-floating-divider-outer: var(--dh-color-gray-50); + + /* Overflow Button */ + --dh-color-grid-overflow-button: var(--dh-color-gray-700); + --dh-color-grid-overflow-button-hover: var(--dh-color-gray-900); + + /* Data Bars */ + --dh-color-grid-data-bar-positive: var(--dh-color-visual-positive); + --dh-color-grid-data-bar-negative: var(--dh-color-visual-negative); + --dh-color-grid-data-bar-marker: var(--dh-color-white); + --dh-color-grid-data-bar-zero-line: var(--dh-color-gray-300); + + /* Scrim */ + --dh-color-grid-scrim: var(--dh-color-gray-50); } diff --git a/packages/components/src/theme/theme-dark/theme-dark-semantic.css b/packages/components/src/theme/theme-dark/theme-dark-semantic.css index 34bea973d8..f3a003352f 100644 --- a/packages/components/src/theme/theme-dark/theme-dark-semantic.css +++ b/packages/components/src/theme/theme-dark/theme-dark-semantic.css @@ -1,3 +1,4 @@ +/* stylelint-disable custom-property-empty-line-before */ /* stylelint-disable alpha-value-notation */ :root { /* General */ @@ -8,9 +9,33 @@ --dh-color-content-background: var(--dh-color-gray-100); /* Text */ + --dh-color-heading-text: var(--dh-color-gray-900); --dh-color-text: var(--dh-color-gray-800); + --dh-color-text-disabled: var(--dh-color-gray-400); --dh-color-text-highlight: hsla(var(--dh-color-blue-hue), 83%, 62%, 0.3); + /** Accent Colors */ + --dh-color-accent-100: var(--dh-color-blue-100); + --dh-color-accent-200: var(--dh-color-blue-200); + --dh-color-accent-300: var(--dh-color-blue-300); + --dh-color-accent-400: var(--dh-color-blue-400); + --dh-color-accent-500: var(--dh-color-blue-500); + --dh-color-accent-600: var(--dh-color-blue-600); + --dh-color-accent-700: var(--dh-color-blue-700); + --dh-color-accent-800: var(--dh-color-blue-800); + --dh-color-accent-900: var(--dh-color-blue-900); + --dh-color-accent-1000: var(--dh-color-blue-1000); + --dh-color-accent-1100: var(--dh-color-blue-1100); + --dh-color-accent-1200: var(--dh-color-blue-1200); + --dh-color-accent-1300: var(--dh-color-blue-1300); + --dh-color-accent-1400: var(--dh-color-blue-1400); + + /* Accent Background */ + --dh-color-accent-background-default: var(--dh-color-accent-600); + --dh-color-accent-background-hover: var(--dh-color-accent-500); + --dh-color-accent-background-down: var(--dh-color-accent-400); + --dh-color-accent-background-key-focus: var(--dh-color-accent-500); + /* Focus */ --dh-color-focus: var(--dh-color-blue-800); --dh-color-focus-border: var(--dh-color-blue-800); @@ -28,6 +53,12 @@ 0.2 ); + /* Negative Background */ + --dh-color-negative-background-default: var(--dh-color-red-600); + --dh-color-negative-background-hover: var(--dh-color-red-500); + --dh-color-negative-background-down: var(--dh-color-red-400); + --dh-color-negative-background-key-focus: var(--dh-color-red-500); + /* Visual Colors */ --dh-color-visual-blue: var(--dh-color-blue-700); --dh-color-visual-celery: var(--dh-color-celery-1000); @@ -44,31 +75,7 @@ --dh-color-visual-seafoam: var(--dh-color-seafoam-1100); --dh-color-visual-yellow: var(--dh-color-yellow-1200); - /** Accent Colors */ - --dh-color-accent-100: var(--dh-color-blue-100); - --dh-color-accent-200: var(--dh-color-blue-200); - --dh-color-accent-300: var(--dh-color-blue-300); - --dh-color-accent-400: var(--dh-color-blue-400); - --dh-color-accent-500: var(--dh-color-blue-500); - --dh-color-accent-600: var(--dh-color-blue-600); - --dh-color-accent-700: var(--dh-color-blue-700); - --dh-color-accent-800: var(--dh-color-blue-800); - --dh-color-accent-900: var(--dh-color-blue-900); - --dh-color-accent-1000: var(--dh-color-blue-1000); - --dh-color-accent-1100: var(--dh-color-blue-1100); - --dh-color-accent-1200: var(--dh-color-blue-1200); - --dh-color-accent-1300: var(--dh-color-blue-1300); - --dh-color-accent-1400: var(--dh-color-blue-1400); - - /* Accent Background */ - --dh-color-accent-background-default: var(--dh-color-accent-600); - --dh-color-accent-background-hover: var(--dh-color-accent-500); - --dh-color-accent-background-down: var(--dh-color-accent-400); - --dh-color-accent-background-key-focus: var(--dh-color-accent-500); - - /* Negative Background */ - --dh-color-negative-background-default: var(--dh-color-red-600); - --dh-color-negative-background-hover: var(--dh-color-red-500); - --dh-color-negative-background-down: var(--dh-color-red-400); - --dh-color-negative-background-key-focus: var(--dh-color-red-500); + --dh-color-visual-positive: var(--dh-color-green-1100); + --dh-color-visual-negative: var(--dh-color-red-800); + --dh-color-visual-notice: var(--dh-color-yellow-1200); } diff --git a/packages/components/src/theme/theme-light/theme-light-palette.css b/packages/components/src/theme/theme-light/theme-light-palette.css index ce7c31acc7..babcf63c22 100644 --- a/packages/components/src/theme/theme-light/theme-light-palette.css +++ b/packages/components/src/theme/theme-light/theme-light-palette.css @@ -50,5 +50,5 @@ --dh-color-accent: var(--dh-color-blue-700); --dh-color-background: var(--dh-color-white); --dh-color-foreground: var(--dh-color-black); - --dh-color-grid-background: var(--dh-color-background); + --dh-color-grid-bg: var(--dh-color-background); } diff --git a/packages/console/CHANGELOG.md b/packages/console/CHANGELOG.md index 35e9a56f2a..2b80a39ecc 100644 --- a/packages/console/CHANGELOG.md +++ b/packages/console/CHANGELOG.md @@ -3,6 +3,29 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +* fix!: CSS based loading spinner (#1532) ([f06fbb0](https://github.com/deephaven/web-client-ui/commit/f06fbb01e27eaaeccab6031d8ff010ffee303d99)), closes [#1532](https://github.com/deephaven/web-client-ui/issues/1532) [#1531](https://github.com/deephaven/web-client-ui/issues/1531) + + +### Features + +* Monaco theming ([#1560](https://github.com/deephaven/web-client-ui/issues/1560)) ([4eda17c](https://github.com/deephaven/web-client-ui/commit/4eda17c82f6c177a11ba600d6f43c4f36915f6bd)), closes [#1542](https://github.com/deephaven/web-client-ui/issues/1542) + + +### BREAKING CHANGES + +* Theme variables have to be present on body to avoid +Monaco init failing +* Inline LoadingSpinner instances will need to be +decorated with `className="loading-spinner-vertical-align"` for vertical +alignment to work as before + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) **Note:** Version bump only for package @deephaven/console diff --git a/packages/console/package.json b/packages/console/package.json index f4b830ae4c..c5e501e145 100644 --- a/packages/console/package.json +++ b/packages/console/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/console", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven Console", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/console/src/Console.tsx b/packages/console/src/Console.tsx index e09f07d010..9d0eb6571b 100644 --- a/packages/console/src/Console.tsx +++ b/packages/console/src/Console.tsx @@ -79,6 +79,8 @@ interface ConsoleProps { * (file:File) => Promise */ unzip: (file: File) => Promise; + supportsType: (type: string) => boolean; + iconForType: (type: string) => ReactElement; } interface ConsoleState { @@ -105,6 +107,16 @@ interface ConsoleState { isPrintStdOutEnabled: boolean; isClosePanelsOnDisconnectEnabled: boolean; } + +function defaultSupportsType(): boolean { + return true; +} + +function defaultIconForType(type: string): ReactElement { + // eslint-disable-next-line react/jsx-no-useless-fragment + return <>; +} + export class Console extends PureComponent { static defaultProps = { statusBarChildren: null, @@ -117,6 +129,8 @@ export class Console extends PureComponent { objectMap: new Map(), disabled: false, unzip: null, + supportsType: defaultSupportsType, + iconForType: defaultIconForType, }; static LOG_THROTTLE = 500; @@ -951,6 +965,8 @@ export class Console extends PureComponent { timeZone, disabled, unzip, + supportsType, + iconForType, } = this.props; const { consoleHeight, @@ -1013,6 +1029,8 @@ export class Console extends PureComponent { openObject={openObject} language={language} disabled={disabled} + supportsType={supportsType} + iconForType={iconForType} /> {historyChildren} diff --git a/packages/console/src/console-history/ConsoleHistory.tsx b/packages/console/src/console-history/ConsoleHistory.tsx index 268684d3cd..4d5a8f22ba 100644 --- a/packages/console/src/console-history/ConsoleHistory.tsx +++ b/packages/console/src/console-history/ConsoleHistory.tsx @@ -1,7 +1,7 @@ /** * Console display for use in the Iris environment. */ -import React, { Component, ReactElement } from 'react'; +import { type ReactElement } from 'react'; import type { VariableDefinition } from '@deephaven/jsapi-types'; import ConsoleHistoryItem from './ConsoleHistoryItem'; @@ -13,43 +13,45 @@ interface ConsoleHistoryProps { language: string; openObject: (object: VariableDefinition) => void; disabled?: boolean; + supportsType(type: string): boolean; + iconForType(type: string): ReactElement; } -class ConsoleHistory extends Component< - ConsoleHistoryProps, - Record -> { - static defaultProps = { - disabled: false, - }; - - static itemKey(i: number, item: ConsoleHistoryActionItem): string { - return `${i}.${item.command}.${item.result && item.result.message}.${ - item.result && item.result.error - }`; - } - - render(): ReactElement { - const { disabled, items, language, openObject } = this.props; - const historyElements = []; - for (let i = 0; i < items.length; i += 1) { - const item = items[i]; - const historyElement = ( - - ); - historyElements.push(historyElement); - } +function itemKey(i: number, item: ConsoleHistoryActionItem): string { + return `${i}.${item.command}.${item.result && item.result.message}.${ + item.result && item.result.error + }`; +} - return ( -
{historyElements}
+function ConsoleHistory(props: ConsoleHistoryProps): ReactElement { + const { + disabled = false, + items, + language, + openObject, + supportsType, + iconForType, + } = props; + const historyElements = []; + for (let i = 0; i < items.length; i += 1) { + const item = items[i]; + const historyElement = ( + ); + historyElements.push(historyElement); } + + return ( +
{historyElements}
+ ); } export default ConsoleHistory; diff --git a/packages/console/src/console-history/ConsoleHistoryItem.tsx b/packages/console/src/console-history/ConsoleHistoryItem.tsx index 2746377ba9..eb85d163f1 100644 --- a/packages/console/src/console-history/ConsoleHistoryItem.tsx +++ b/packages/console/src/console-history/ConsoleHistoryItem.tsx @@ -6,7 +6,7 @@ import { Button } from '@deephaven/components'; import Log from '@deephaven/log'; import type { VariableDefinition } from '@deephaven/jsapi-types'; import classNames from 'classnames'; -import { Code, ObjectIcon } from '../common'; +import { Code } from '../common'; import ConsoleHistoryItemResult from './ConsoleHistoryItemResult'; import ConsoleHistoryResultInProgress from './ConsoleHistoryResultInProgress'; import ConsoleHistoryResultErrorMessage from './ConsoleHistoryResultErrorMessage'; @@ -20,6 +20,10 @@ interface ConsoleHistoryItemProps { language: string; openObject: (object: VariableDefinition) => void; disabled?: boolean; + // TODO: #1573 Remove this eslint disable + // eslint-disable-next-line react/no-unused-prop-types + supportsType: (type: string) => boolean; + iconForType: (type: string) => ReactElement; } class ConsoleHistoryItem extends PureComponent< @@ -53,7 +57,7 @@ class ConsoleHistoryItem extends PureComponent< } render(): ReactElement { - const { disabled, item, language } = this.props; + const { disabled, item, language, iconForType } = this.props; const { disabledObjects, result } = item; const hasCommand = item.command != null && item.command !== ''; @@ -77,6 +81,9 @@ class ConsoleHistoryItem extends PureComponent< if (changes) { const { created, updated } = changes; + // TODO: #1573 filter for supported types or change button kind + // based on if type is supported. Possibly a warn state for widgets + // that the UI doesn't have anything registered to support. [...created, ...updated].forEach(object => { hasButtons = true; const { title } = object; @@ -92,7 +99,7 @@ class ConsoleHistoryItem extends PureComponent< onClick={() => this.handleObjectClick(object)} className="btn-console-object" disabled={btnDisabled} - icon={} + icon={iconForType(object.type)} > {title} diff --git a/packages/console/src/monaco/MonacoTheme.module.scss b/packages/console/src/monaco/MonacoTheme.module.scss index 7185cb8386..35e688c29d 100644 --- a/packages/console/src/monaco/MonacoTheme.module.scss +++ b/packages/console/src/monaco/MonacoTheme.module.scss @@ -3,9 +3,9 @@ :export { // iris dark theme - error-foreground: var(--dh-color-editor-error-foreground); - background: var(--dh-color-editor-background); - foreground: var(--dh-color-editor-foreground); + error-foreground: var(--dh-color-editor-error-fg); + background: var(--dh-color-editor-bg); + foreground: var(--dh-color-editor-fg); line-height: 19px; // 19 is the line height in the default monaco theme //code rules @@ -25,19 +25,19 @@ //input input-option-active-border: var(--dh-color-editor-input-option-active-border); focus-border: var(--dh-color-editor-focus-border); - input-background: var(--dh-color-editor-input-background); - input-foreground: var(--dh-color-editor-input-foreground); + input-background: var(--dh-color-editor-input-bg); + input-foreground: var(--dh-color-editor-input-fg); input-border: var(--dh-color-editor-input-border); //editor - editor-line-number-foreground: var(--dh-color-editor-line-number-foreground); - editor-selection-background: var(--dh-color-editor-selection-background); + editor-line-number-foreground: var(--dh-color-editor-line-number-fg); + editor-selection-background: var(--dh-color-editor-selection-bg); editor-line-highlight-bg: var(--dh-color-editor-line-highlight-bg); //context menu - context-menu-background: var(--dh-color-editor-context-menu-background); - context-menu-foreground: var(--dh-color-editor-context-menu-foreground); - menu-selection-background: var(--dh-color-editor-menu-selection-background); + context-menu-background: var(--dh-color-editor-context-menu-bg); + context-menu-foreground: var(--dh-color-editor-context-menu-fg); + menu-selection-background: var(--dh-color-editor-menu-selection-bg); //log items log-date: var(--dh-color-editor-log-date); @@ -49,34 +49,30 @@ log-trace: var(--dh-color-editor-log-trace); // find matches - editor-find-match-background: var(--dh-color-editor-find-match-background); + editor-find-match-background: var(--dh-color-editor-find-match-bg); editor-find-match-highlight-background: var( - --dh-color-editor-find-match-highlight-background + --dh-color-editor-find-match-highlight-bg ); // find widget - editor-widget-background: var(--dh-color-editor-find-background); - input-option-active-background: var( - --dh-color-editor-find-option-active-background - ); - input-option-active-foreground: var( - --dh-color-editor-find-option-active-foreground - ); + editor-widget-background: var(--dh-color-editor-find-bg); + input-option-active-background: var(--dh-color-editor-find-option-active-bg); + input-option-active-foreground: var(--dh-color-editor-find-option-active-fg); // suggest widget - editor-suggest-widget-background: var(--dh-color-editor-suggest-background); + editor-suggest-widget-background: var(--dh-color-editor-suggest-bg); editor-suggest-widget-border: var(--dh-color-editor-suggest-border); - editor-suggest-widget-foreground: var(--dh-color-editor-suggest-foreground); + editor-suggest-widget-foreground: var(--dh-color-editor-suggest-fg); editor-suggest-widget-selected-background: var( - --dh-color-editor-suggest-selected-background + --dh-color-editor-suggest-selected-bg ); editor-suggest-widget-highlightForeground: var( - --dh-color-editor-suggest-highlight-foreground + --dh-color-editor-suggest-highlight-fg ); - list-hover-background: var(--dh-color-editor-suggest-hover-background); + list-hover-background: var(--dh-color-editor-suggest-hover-bg); // links text-link-foreground: var(--dh-color-editor-link-foreground); - text-link-active-foreground: var(--dh-color-editor-link-active-foreground); - editor-link-active-foreground: var(--dh-color-editor-link-active-foreground); + text-link-active-foreground: var(--dh-color-editor-link-active-fg); + editor-link-active-foreground: var(--dh-color-editor-link-active-fg); } diff --git a/packages/dashboard-core-plugins/CHANGELOG.md b/packages/dashboard-core-plugins/CHANGELOG.md index 4cb2fa43da..01e806bc44 100644 --- a/packages/dashboard-core-plugins/CHANGELOG.md +++ b/packages/dashboard-core-plugins/CHANGELOG.md @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Bug Fixes + +* Handle deletion of unsaved copied file in NotebookPanel ([#1557](https://github.com/deephaven/web-client-ui/issues/1557)) ([4021aac](https://github.com/deephaven/web-client-ui/commit/4021aac3bc130f8eec84385c9aadcb4ecf0b995c)), closes [#1359](https://github.com/deephaven/web-client-ui/issues/1359) +* Prompt for resetting layout ([#1552](https://github.com/deephaven/web-client-ui/issues/1552)) ([a273e64](https://github.com/deephaven/web-client-ui/commit/a273e6433a81f5500fb39992cac276bcbdbda753)), closes [#1250](https://github.com/deephaven/web-client-ui/issues/1250) + + +* fix!: CSS based loading spinner (#1532) ([f06fbb0](https://github.com/deephaven/web-client-ui/commit/f06fbb01e27eaaeccab6031d8ff010ffee303d99)), closes [#1532](https://github.com/deephaven/web-client-ui/issues/1532) [#1531](https://github.com/deephaven/web-client-ui/issues/1531) + + +### Features + +* Add copy/rename/delete options to notebook overflow menu ([#1551](https://github.com/deephaven/web-client-ui/issues/1551)) ([4441109](https://github.com/deephaven/web-client-ui/commit/4441109d10dcee8a9415b6884114ee5083fd1cc0)), closes [#1359](https://github.com/deephaven/web-client-ui/issues/1359) + + +### BREAKING CHANGES + +* Inline LoadingSpinner instances will need to be +decorated with `className="loading-spinner-vertical-align"` for vertical +alignment to work as before + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) **Note:** Version bump only for package @deephaven/dashboard-core-plugins diff --git a/packages/dashboard-core-plugins/package.json b/packages/dashboard-core-plugins/package.json index b6dd152e5b..dd11bfc45e 100644 --- a/packages/dashboard-core-plugins/package.json +++ b/packages/dashboard-core-plugins/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/dashboard-core-plugins", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven Dashboard Core Plugins", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/dashboard-core-plugins/src/PandasPlugin.tsx b/packages/dashboard-core-plugins/src/PandasPlugin.tsx index c7d3594c6c..756ed0c3aa 100644 --- a/packages/dashboard-core-plugins/src/PandasPlugin.tsx +++ b/packages/dashboard-core-plugins/src/PandasPlugin.tsx @@ -1,28 +1,23 @@ -import { - assertIsDashboardPluginProps, - DashboardPluginComponentProps, - useDashboardPanel, -} from '@deephaven/dashboard'; -import { useApi } from '@deephaven/jsapi-bootstrap'; +import { DashboardPanelProps } from '@deephaven/dashboard'; +import { WidgetComponentProps } from '@deephaven/plugin'; +import { forwardRef, useMemo } from 'react'; import { PandasPanel } from './panels'; import useHydrateGrid from './useHydrateGrid'; -export function PandasPlugin( - props: DashboardPluginComponentProps -): JSX.Element | null { - assertIsDashboardPluginProps(props); - const dh = useApi(); - const hydrate = useHydrateGrid(); +export const PandasPlugin = forwardRef( + (props: WidgetComponentProps, ref: React.Ref) => { + const hydrate = useHydrateGrid(); + const { localDashboardId } = props; + const hydratedProps = useMemo( + () => hydrate(props, localDashboardId), + [hydrate, props, localDashboardId] + ); - useDashboardPanel({ - dashboardProps: props, - componentName: PandasPanel.COMPONENT, - component: PandasPanel, - supportedTypes: dh.VariableType.PANDAS, - hydrate, - }); + // eslint-disable-next-line react/jsx-props-no-spreading + return ; + } +); - return null; -} +PandasPlugin.displayName = 'PandasPlugin'; export default PandasPlugin; diff --git a/packages/dashboard-core-plugins/src/PandasPluginConfig.ts b/packages/dashboard-core-plugins/src/PandasPluginConfig.ts index 2d65ccff26..d34828413a 100644 --- a/packages/dashboard-core-plugins/src/PandasPluginConfig.ts +++ b/packages/dashboard-core-plugins/src/PandasPluginConfig.ts @@ -1,10 +1,16 @@ -import { PluginType, DashboardPlugin } from '@deephaven/plugin'; +import { PluginType, WidgetPlugin } from '@deephaven/plugin'; +import { dhPandas } from '@deephaven/icons'; import PandasPlugin from './PandasPlugin'; -const PandasPluginConfig: DashboardPlugin = { +const PandasPluginConfig: WidgetPlugin = { name: 'PandasPlugin', - type: PluginType.DASHBOARD_PLUGIN, + title: 'Pandas', + type: PluginType.WIDGET_PLUGIN, + // TODO: #1573 Replace with actual base component and not just the panel plugin component: PandasPlugin, + panelComponent: PandasPlugin, + supportedTypes: 'pandas.DataFrame', + icon: dhPandas, }; export default PandasPluginConfig; diff --git a/packages/dashboard-core-plugins/src/WidgetLoaderPlugin.test.tsx b/packages/dashboard-core-plugins/src/WidgetLoaderPlugin.test.tsx new file mode 100644 index 0000000000..77c12c3f6f --- /dev/null +++ b/packages/dashboard-core-plugins/src/WidgetLoaderPlugin.test.tsx @@ -0,0 +1,275 @@ +import React from 'react'; +import { render, screen, act } from '@testing-library/react'; +import { + PluginType, + type WidgetPlugin, + type WidgetComponentProps, +} from '@deephaven/plugin'; +import { Provider } from 'react-redux'; +import { Dashboard, PanelEvent } from '@deephaven/dashboard'; +import { createMockStore } from '@deephaven/redux'; +import { dh } from '@deephaven/jsapi-shim'; +import { ApiContext } from '@deephaven/jsapi-bootstrap'; +import { type IdeConnection } from '@deephaven/jsapi-types'; +import { ConnectionContext, PluginsContext } from '@deephaven/app-utils'; +import { + type LayoutManager, + EventEmitter, + type ItemContainer, +} from '@deephaven/golden-layout'; +import { assertNotNull } from '@deephaven/utils'; +import WidgetLoaderPlugin, { WrapWidgetPlugin } from './WidgetLoaderPlugin'; +import WidgetLoaderPluginConfig from './WidgetLoaderPluginConfig'; + +function TestWidget() { + return
TestWidget
; +} + +function TestWidgetTwo() { + return
TestWidgetTwo
; +} + +function TestPanel() { + return
TestPanel
; +} + +class TestForwardRef extends React.PureComponent { + render() { + return
TestForwardRef
; + } +} + +const testWidgetPlugin: WidgetPlugin = { + component: TestWidget, + name: 'widget', + title: 'Widget', + type: PluginType.WIDGET_PLUGIN, + supportedTypes: 'test-widget', +}; + +const testWidgetPluginWithPanel: WidgetPlugin = { + name: 'widget-with-panel', + title: 'Widget', + type: PluginType.WIDGET_PLUGIN, + supportedTypes: 'test-widget-panel', + component: TestWidget, + panelComponent: TestPanel, +}; + +const testWidgetRefPlugin: WidgetPlugin = { + component: TestForwardRef, + name: 'widget', + title: 'Widget', + type: PluginType.WIDGET_PLUGIN, + supportedTypes: 'test-widget-ref', +}; + +function makeConnection(): IdeConnection { + const connection = new dh.IdeConnection('http://mockserver'); + connection.getObject = jest.fn(); + return connection; +} + +const DEFAULT_PLUGINS = [ + ['test-widget-plugin', testWidgetPlugin], + ['test-widget-plugin-with-panel', testWidgetPluginWithPanel], + ['test-dashboard-plugin', WidgetLoaderPluginConfig], +] as [string, WidgetPlugin][]; + +function createAndMountDashboard( + plugins: [string, WidgetPlugin][] = DEFAULT_PLUGINS +) { + const store = createMockStore(); + const connection = makeConnection(); + let layoutManager: LayoutManager | undefined; + + render( + + + (plugins)}> + + { + layoutManager = newLayout; + }} + > + + + + + + + ); + assertNotNull(layoutManager); + return layoutManager; +} + +describe('WidgetLoaderPlugin', () => { + it('Mounts components that should be wrapped', async () => { + const layoutManager = createAndMountDashboard(); + + act( + () => + layoutManager?.eventHub.emit(PanelEvent.OPEN, { + widget: { type: 'test-widget' }, + }) + ); + expect(screen.queryAllByText('TestWidget').length).toBe(1); + }); + + it('Mounts components that should not be wrapped', async () => { + const layoutManager = createAndMountDashboard(); + + act( + () => + layoutManager?.eventHub.emit(PanelEvent.OPEN, { + widget: { type: 'test-widget-panel' }, + }) + ); + expect(screen.queryAllByText('TestPanel').length).toBe(1); + }); + + it('Handles plugins with multiple supported types', async () => { + const layoutManager = createAndMountDashboard([ + [ + 'test-widget-plugin-two', + { + name: 'test-widget-plugin-two', + type: PluginType.WIDGET_PLUGIN, + component: TestWidgetTwo, + supportedTypes: ['test-widget-two-a', 'test-widget-two-b'], + }, + ], + ]); + + act( + () => + layoutManager?.eventHub.emit(PanelEvent.OPEN, { + widget: { type: 'test-widget-two-a' }, + }) + ); + expect(screen.queryAllByText('TestWidgetTwo').length).toBe(1); + + act( + () => + layoutManager?.eventHub.emit(PanelEvent.OPEN, { + widget: { type: 'test-widget-two-b' }, + }) + ); + expect(screen.queryAllByText('TestWidgetTwo').length).toBe(2); + }); + + it('Ignores unknown widget types', async () => { + const layoutManager = createAndMountDashboard(); + + act( + () => + layoutManager?.eventHub.emit(PanelEvent.OPEN, { + widget: { type: 'unknown-widget' }, + }) + ); + expect(screen.queryAllByText('TestWidget').length).toBe(0); + expect(screen.queryAllByText('TestPanel').length).toBe(0); + }); + + it('Does not mount if the plugin does not have supportedTypes', async () => { + const layoutManager = createAndMountDashboard([ + [ + testWidgetPlugin.name, + { + ...testWidgetPlugin, + supportedTypes: undefined, + }, + ], + ]); + + act( + () => + layoutManager?.eventHub.emit(PanelEvent.OPEN, { + widget: { type: 'test-widget' }, + }) + ); + expect(screen.queryAllByText('TestWidget').length).toBe(0); + }); + + it('Overrides plugins that handle the same widget type', async () => { + const layoutManager = createAndMountDashboard([ + [ + 'test-widget-plugin', + { + ...testWidgetPlugin, + supportedTypes: ['test-widget', 'test-widget-a'], + }, + ], + [ + 'test-widget-plugin-two', + { + name: 'test-widget-plugin-two', + type: PluginType.WIDGET_PLUGIN, + component: TestWidgetTwo, + supportedTypes: 'test-widget', + }, + ], + ]); + + act( + () => + layoutManager?.eventHub.emit(PanelEvent.OPEN, { + widget: { type: 'test-widget' }, + }) + ); + expect(screen.queryAllByText('TestWidget').length).toBe(0); + expect(screen.queryAllByText('TestWidgetTwo').length).toBe(1); + + act( + () => + layoutManager?.eventHub.emit(PanelEvent.OPEN, { + widget: { type: 'test-widget-a' }, + }) + ); + expect(screen.queryAllByText('TestWidget').length).toBe(1); + expect(screen.queryAllByText('TestWidgetTwo').length).toBe(1); + }); +}); + +describe('component wrapper', () => { + it('should forward callback refs', () => { + let refObj; + const ref = jest.fn(r => { + refObj = r; + }); + const Wrapper = WrapWidgetPlugin(testWidgetRefPlugin); + render( + + ); + expect(ref).toBeCalledTimes(1); + expect(refObj).toBeInstanceOf(TestForwardRef); + }); + + it('should forward non-callback refs', () => { + const ref = React.createRef(); + const Wrapper = WrapWidgetPlugin(testWidgetRefPlugin); + render( + + ); + expect(ref.current).toBeInstanceOf(TestForwardRef); + }); + + it('should not error if no ref passed', () => { + const Wrapper = WrapWidgetPlugin(testWidgetRefPlugin); + render( + + ); + }); +}); diff --git a/packages/dashboard-core-plugins/src/WidgetLoaderPlugin.tsx b/packages/dashboard-core-plugins/src/WidgetLoaderPlugin.tsx new file mode 100644 index 0000000000..b618adb1e8 --- /dev/null +++ b/packages/dashboard-core-plugins/src/WidgetLoaderPlugin.tsx @@ -0,0 +1,183 @@ +import { + useMemo, + useCallback, + type ComponentType, + useEffect, + forwardRef, + useState, +} from 'react'; +import type { ReactComponentConfig } from '@deephaven/golden-layout'; +import shortid from 'shortid'; +import { + assertIsDashboardPluginProps, + DashboardPluginComponentProps, + DehydratedDashboardPanelProps, + PanelEvent, + PanelOpenEventDetail, + LayoutUtils, + useListener, + PanelProps, + canHaveRef, +} from '@deephaven/dashboard'; +import { usePlugins } from '@deephaven/app-utils'; +import { isWidgetPlugin, type WidgetPlugin } from '@deephaven/plugin'; +import Log from '@deephaven/log'; +import { WidgetPanel } from './panels'; + +const log = Log.module('WidgetLoaderPlugin'); + +export function WrapWidgetPlugin( + plugin: WidgetPlugin +): React.ForwardRefExoticComponent> { + function Wrapper(props: PanelProps, ref: React.ForwardedRef) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const C = plugin.component as any; + const { metadata } = props; + const [componentPanel, setComponentPanel] = useState(); + const refCallback = useCallback( + (e: ComponentType) => { + setComponentPanel(e); + if (typeof ref === 'function') { + ref(e); + } else if (ref != null) { + // eslint-disable-next-line no-param-reassign + ref.current = e; + } + }, + [ref] + ); + + const hasRef = canHaveRef(C); + + return ( + + {hasRef ? ( + + ) : ( + + )} + ) + + ); + } + + Wrapper.displayName = `WidgetLoaderPlugin(${ + plugin.component.displayName ?? plugin.name + })`; + + return forwardRef(Wrapper); +} + +/** + * Widget to automatically open any supported WidgetPlugin types as panels + * if the widget is emitted from the server as the result of executed code. + * + * Does not open panels for widgets that are not supported by any plugins. + * Does not open panels for widgets that are a component of a larger widget or UI element. + * + * @param props Dashboard plugin props + * @returns React element + */ +export function WidgetLoaderPlugin( + props: Partial +): JSX.Element | null { + const plugins = usePlugins(); + const supportedTypes = useMemo(() => { + const typeMap = new Map(); + plugins.forEach(plugin => { + if (!isWidgetPlugin(plugin)) { + return; + } + + [plugin.supportedTypes].flat().forEach(supportedType => { + if (supportedType != null && supportedType !== '') { + if (typeMap.has(supportedType)) { + log.warn( + `Multiple WidgetPlugins handling type ${supportedType}. Replacing ${typeMap.get( + supportedType + )?.name} with ${plugin.name} to handle ${supportedType}` + ); + } + typeMap.set(supportedType, plugin); + } + }); + }); + + return typeMap; + }, [plugins]); + + assertIsDashboardPluginProps(props); + const { id, layout, registerComponent } = props; + + const handlePanelOpen = useCallback( + ({ + dragEvent, + fetch, + panelId = shortid.generate(), + widget, + }: PanelOpenEventDetail) => { + const { id: widgetId, type } = widget; + const name = widget.title ?? widget.name; + const plugin = supportedTypes.get(type); + if (plugin == null) { + return; + } + const metadata = { id: widgetId, name, type }; + const panelProps: DehydratedDashboardPanelProps & { + fetch?: typeof fetch; + } = { + localDashboardId: id, + metadata, + fetch, + }; + + const config: ReactComponentConfig = { + type: 'react-component', + component: plugin.name, + props: panelProps, + title: name, + id: panelId, + }; + + const { root } = layout; + LayoutUtils.openComponent({ root, config, dragEvent }); + }, + [id, layout, supportedTypes] + ); + + useEffect(() => { + const deregisterFns = [...new Set(supportedTypes.values())].map(plugin => { + const { panelComponent } = plugin; + if (panelComponent == null) { + return registerComponent(plugin.name, WrapWidgetPlugin(plugin)); + } + return registerComponent(plugin.name, panelComponent); + }); + + return () => { + deregisterFns.forEach(deregister => deregister()); + }; + }); + + /** + * Listen for panel open events so we know when to open a panel + */ + useListener(layout.eventHub, PanelEvent.OPEN, handlePanelOpen); + + return null; +} + +export default WidgetLoaderPlugin; diff --git a/packages/dashboard-core-plugins/src/WidgetLoaderPluginConfig.ts b/packages/dashboard-core-plugins/src/WidgetLoaderPluginConfig.ts new file mode 100644 index 0000000000..707e396c6b --- /dev/null +++ b/packages/dashboard-core-plugins/src/WidgetLoaderPluginConfig.ts @@ -0,0 +1,10 @@ +import { PluginType, DashboardPlugin } from '@deephaven/plugin'; +import WidgetLoaderPlugin from './WidgetLoaderPlugin'; + +const WidgetLoaderPluginConfig: DashboardPlugin = { + name: 'WidgetLoaderPlugin', + type: PluginType.DASHBOARD_PLUGIN, + component: WidgetLoaderPlugin, +}; + +export default WidgetLoaderPluginConfig; diff --git a/packages/dashboard-core-plugins/src/index.test.tsx b/packages/dashboard-core-plugins/src/index.test.tsx index 648871569c..d0a5cd2cdc 100644 --- a/packages/dashboard-core-plugins/src/index.test.tsx +++ b/packages/dashboard-core-plugins/src/index.test.tsx @@ -14,7 +14,7 @@ import { GridPlugin, LinkerPlugin, MarkdownPlugin, - PandasPlugin, + WidgetLoaderPlugin, } from '.'; function makeConnection(): IdeConnection { @@ -40,7 +40,7 @@ it('handles mounting and unmount core plugins properly', () => { - undefined} /> + diff --git a/packages/dashboard-core-plugins/src/index.ts b/packages/dashboard-core-plugins/src/index.ts index 2fd12c776c..c1f9b7882b 100644 --- a/packages/dashboard-core-plugins/src/index.ts +++ b/packages/dashboard-core-plugins/src/index.ts @@ -13,6 +13,8 @@ export { default as MarkdownPlugin } from './MarkdownPlugin'; export { default as MarkdownPluginConfig } from './MarkdownPluginConfig'; export { default as PandasPlugin } from './PandasPlugin'; export { default as PandasPluginConfig } from './PandasPluginConfig'; +export { default as WidgetLoaderPlugin } from './WidgetLoaderPlugin'; +export { default as WidgetLoaderPluginConfig } from './WidgetLoaderPluginConfig'; export { default as ControlType } from './controls/ControlType'; export { default as LinkerUtils } from './linker/LinkerUtils'; export type { Link } from './linker/LinkerUtils'; diff --git a/packages/dashboard-core-plugins/src/panels/ConsolePanel.tsx b/packages/dashboard-core-plugins/src/panels/ConsolePanel.tsx index be543e3fb5..25998a7dd6 100644 --- a/packages/dashboard-core-plugins/src/panels/ConsolePanel.tsx +++ b/packages/dashboard-core-plugins/src/panels/ConsolePanel.tsx @@ -9,17 +9,21 @@ import { Console, ConsoleConstants, HeapUsage, + ObjectIcon, } from '@deephaven/console'; import { DashboardPanelProps, PanelEvent } from '@deephaven/dashboard'; import type { IdeSession, VariableDefinition } from '@deephaven/jsapi-types'; import { SessionWrapper } from '@deephaven/jsapi-utils'; import Log from '@deephaven/log'; import { + DeephavenPluginModuleMap, getCommandHistoryStorage, + getPlugins, getTimeZone, RootState, } from '@deephaven/redux'; import { assertNotNull } from '@deephaven/utils'; +import { getIconForPlugin, pluginSupportsType } from '@deephaven/plugin'; import type { JSZipObject } from 'jszip'; import { ConsoleEvent } from '../events'; import Panel from './Panel'; @@ -55,6 +59,7 @@ interface ConsolePanelProps extends DashboardPanelProps { timeZone: string; unzip?: (file: File) => Promise; + plugins: DeephavenPluginModuleMap; } interface ConsolePanelState { @@ -86,6 +91,8 @@ export class ConsolePanel extends PureComponent< this.handleSettingsChange = this.handleSettingsChange.bind(this); this.handleShow = this.handleShow.bind(this); this.handlePanelMount = this.handlePanelMount.bind(this); + this.supportsType = this.supportsType.bind(this); + this.iconForType = this.iconForType.bind(this); this.consoleRef = React.createRef(); @@ -308,6 +315,23 @@ export class ConsolePanel extends PureComponent< this.consoleRef.current?.updateDimensions(); } + supportsType(type: string): boolean { + const { plugins } = this.props; + return [...plugins.values()].some(plugin => + pluginSupportsType(plugin, type) + ); + } + + iconForType(type: string): JSX.Element { + const { plugins } = this.props; + const plugin = [...plugins.values()].find(p => pluginSupportsType(p, type)); + if (plugin != null) { + return getIconForPlugin(plugin); + } + // TODO: #1573 Remove this default and always return getIconForPlugin + return ; + } + render(): ReactElement { const { commandHistoryStorage, @@ -378,6 +402,8 @@ export class ConsolePanel extends PureComponent< timeZone={timeZone} objectMap={objectMap} unzip={unzip} + supportsType={this.supportsType} + iconForType={this.iconForType} /> )} @@ -390,13 +416,14 @@ const mapStateToProps = ( ownProps: { localDashboardId: string } ): Pick< ConsolePanelProps, - 'commandHistoryStorage' | 'sessionWrapper' | 'timeZone' + 'commandHistoryStorage' | 'sessionWrapper' | 'timeZone' | 'plugins' > => ({ commandHistoryStorage: getCommandHistoryStorage( state ) as CommandHistoryStorage, sessionWrapper: getDashboardSessionWrapper(state, ownProps.localDashboardId), timeZone: getTimeZone(state), + plugins: getPlugins(state), }); const ConnectedConsolePanel = connect(mapStateToProps, null, null, { diff --git a/packages/dashboard-core-plugins/src/panels/FileExplorerPanel.tsx b/packages/dashboard-core-plugins/src/panels/FileExplorerPanel.tsx index b3f8f53395..1b07cd85be 100644 --- a/packages/dashboard-core-plugins/src/panels/FileExplorerPanel.tsx +++ b/packages/dashboard-core-plugins/src/panels/FileExplorerPanel.tsx @@ -165,20 +165,10 @@ export class FileExplorerPanel extends React.Component< log.error('Invalid item in handleCopyItem', file); return; } - let newName = FileUtils.getCopyFileName(file.filename); - const checkNewName = async (): Promise => { - try { - await fileStorage.info(newName); - return true; - } catch (error) { - return false; - } - }; - // await in loop is fine here, this isn't a parallel task - // eslint-disable-next-line no-await-in-loop - while (await checkNewName()) { - newName = FileUtils.getCopyFileName(newName); - } + const newName = await FileUtils.getUniqueCopyFileName( + fileStorage, + file.filename + ); await fileStorage.copyFile(file.filename, newName); } diff --git a/packages/dashboard-core-plugins/src/panels/IrisGridPanel.tsx b/packages/dashboard-core-plugins/src/panels/IrisGridPanel.tsx index 3c98fc12f7..275fde6ad9 100644 --- a/packages/dashboard-core-plugins/src/panels/IrisGridPanel.tsx +++ b/packages/dashboard-core-plugins/src/panels/IrisGridPanel.tsx @@ -137,25 +137,29 @@ export interface IrisGridPanelProps extends DashboardPanelProps { children?: ReactNode; panelState: LoadedPanelState | null; makeModel: () => IrisGridModel | Promise; + + onStateChange?: (irisGridState: IrisGridState, gridState: GridState) => void; + onPanelStateUpdate?: (panelState: PanelState) => void; + + /** Override the default worker used by IrisGrid to download CSVs. */ + getDownloadWorker?: () => Promise; + + /** Load a plugin defined by the table */ + loadPlugin: (pluginName: string) => TablePluginComponent; + + theme?: IrisGridThemeType; +} + +interface PropsFromRedux { inputFilters: InputFilter[]; links: Link[]; columnSelectionValidator?: ( panel: PanelComponent, tableColumn?: LinkColumn ) => boolean; - onStateChange?: (irisGridState: IrisGridState, gridState: GridState) => void; - onPanelStateUpdate?: (panelState: PanelState) => void; user: User; workspace: Workspace; settings: { timeZone: string }; - - // Retrieve a download worker for optimizing exporting tables - getDownloadWorker: () => Promise; - - // Load a plugin defined by the table - loadPlugin: (pluginName: string) => TablePluginComponent; - - theme: IrisGridThemeType; } interface IrisGridPanelState { @@ -221,8 +225,10 @@ function getTableNameFromMetadata(metadata: PanelMetadata | undefined): string { throw new Error(`Unable to determine table name from metadata: ${metadata}`); } +type IrisGridPanelPropsWithRedux = IrisGridPanelProps & PropsFromRedux; + export class IrisGridPanel extends PureComponent< - IrisGridPanelProps, + IrisGridPanelPropsWithRedux, IrisGridPanelState > { static defaultProps = { @@ -234,7 +240,7 @@ export class IrisGridPanel extends PureComponent< static COMPONENT = 'IrisGridPanel'; - constructor(props: IrisGridPanelProps) { + constructor(props: IrisGridPanelPropsWithRedux) { super(props); this.handleAdvancedSettingsChange = @@ -1379,15 +1385,7 @@ export class IrisGridPanel extends PureComponent< const mapStateToProps = ( state: RootState, { localDashboardId = DEFAULT_DASHBOARD_ID }: { localDashboardId?: string } -): Pick< - IrisGridPanelProps, - | 'columnSelectionValidator' - | 'inputFilters' - | 'links' - | 'settings' - | 'user' - | 'workspace' -> => ({ +) => ({ inputFilters: getInputFiltersForDashboard(state, localDashboardId), links: getLinksForDashboard(state, localDashboardId), columnSelectionValidator: getColumnSelectionValidatorForDashboard( diff --git a/packages/dashboard-core-plugins/src/panels/NotebookPanel.tsx b/packages/dashboard-core-plugins/src/panels/NotebookPanel.tsx index a77867d221..5ec6ad73b7 100644 --- a/packages/dashboard-core-plugins/src/panels/NotebookPanel.tsx +++ b/packages/dashboard-core-plugins/src/panels/NotebookPanel.tsx @@ -681,15 +681,31 @@ class NotebookPanel extends Component { this.focus(); } - handleCopy(): void { + async handleCopy(): Promise { + const { fileStorage, glEventHub, session } = this.props; const { fileMetadata, settings } = this.state; assertNotNull(fileMetadata); - const content = this.getNotebookValue(); const { language } = settings; const { itemName } = fileMetadata; - const copyName = FileUtils.getCopyFileName(itemName); + const copyName = await FileUtils.getUniqueCopyFileName( + fileStorage, + itemName + ); log.debug('handleCopy', fileMetadata, itemName, copyName); - this.createNotebook(copyName, language, content); + await fileStorage.copyFile(itemName, copyName); + const newFileMetadata = { id: copyName, itemName: copyName }; + const notebookSettings = { + value: null, + language, + }; + glEventHub.emit( + NotebookEvent.SELECT_NOTEBOOK, + session, + language, + notebookSettings, + newFileMetadata, + true + ); } handleDelete(): void { @@ -697,7 +713,7 @@ class NotebookPanel extends Component { this.setState({ showDeleteModal: true }); } - handleDeleteConfirm(): void { + async handleDeleteConfirm(): Promise { const { fileStorage, glContainer, glEventHub } = this.props; const { fileMetadata } = this.state; @@ -708,7 +724,11 @@ class NotebookPanel extends Component { return; } - if (FileUtils.hasPath(fileMetadata.itemName)) { + if ( + FileUtils.hasPath(fileMetadata.itemName) && + // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions + (await FileUtils.fileExists(fileStorage, fileMetadata.itemName)) + ) { glEventHub.emit(NotebookEvent.CLOSE_FILE, fileMetadata, { force: true }); fileStorage.deleteFile(fileMetadata.itemName); } else { diff --git a/packages/dashboard-core-plugins/src/panels/Panel.tsx b/packages/dashboard-core-plugins/src/panels/Panel.tsx index 5b02759ca0..237ba74ebc 100644 --- a/packages/dashboard-core-plugins/src/panels/Panel.tsx +++ b/packages/dashboard-core-plugins/src/panels/Panel.tsx @@ -1,5 +1,6 @@ import React, { Component, + ComponentType, FocusEvent, FocusEventHandler, PureComponent, @@ -32,7 +33,7 @@ import RenameDialog from './RenameDialog'; const log = Log.module('Panel'); interface PanelProps { - componentPanel: Component; + componentPanel?: ComponentType | Component; children: ReactNode; glContainer: Container; glEventHub: EventEmitter; @@ -125,7 +126,7 @@ class Panel extends PureComponent { } componentDidMount(): void { - const { componentPanel, glContainer, glEventHub } = this.props; + const { glContainer, glEventHub } = this.props; glContainer.on('resize', this.handleResize); glContainer.on('show', this.handleBeforeShow); @@ -141,8 +142,15 @@ class Panel extends PureComponent { InputFilterEvent.CLEAR_ALL_FILTERS, this.handleClearAllFilters ); + } - glEventHub.emit(PanelEvent.MOUNT, componentPanel); + componentDidUpdate(prevProps: PanelProps): void { + const { componentPanel, glEventHub } = this.props; + + // componentPanel ref could start undefined w/ WidgetLoaderPlugin wrapping panels + if (prevProps.componentPanel == null && componentPanel != null) { + glEventHub.emit(PanelEvent.MOUNT, componentPanel); + } } componentWillUnmount(): void { @@ -163,7 +171,9 @@ class Panel extends PureComponent { this.handleClearAllFilters ); - glEventHub.emit(PanelEvent.UNMOUNT, componentPanel); + if (componentPanel != null) { + glEventHub.emit(PanelEvent.UNMOUNT, componentPanel); + } } handleTab(tab: Tab): void { diff --git a/packages/dashboard-core-plugins/src/panels/WidgetPanel.tsx b/packages/dashboard-core-plugins/src/panels/WidgetPanel.tsx index a214fb149b..a1dbeeb509 100644 --- a/packages/dashboard-core-plugins/src/panels/WidgetPanel.tsx +++ b/packages/dashboard-core-plugins/src/panels/WidgetPanel.tsx @@ -1,5 +1,6 @@ import React, { Component, + ComponentType, PureComponent, ReactElement, ReactNode, @@ -15,7 +16,7 @@ import './WidgetPanel.scss'; interface WidgetPanelProps { children: ReactNode; - componentPanel: Component; + componentPanel?: ComponentType | Component; glContainer: Container; glEventHub: EventEmitter; diff --git a/packages/dashboard-core-plugins/src/useHydrateGrid.ts b/packages/dashboard-core-plugins/src/useHydrateGrid.ts index bf806a82c4..1413070a3e 100644 --- a/packages/dashboard-core-plugins/src/useHydrateGrid.ts +++ b/packages/dashboard-core-plugins/src/useHydrateGrid.ts @@ -9,17 +9,23 @@ import { Table } from '@deephaven/jsapi-types'; import { IrisGridModelFactory } from '@deephaven/iris-grid'; import { IrisGridPanelMetadata, + IrisGridPanelProps, isIrisGridPanelMetadata, isLegacyIrisGridPanelMetadata, } from './panels'; -export function useHydrateGrid(): PanelHydrateFunction { +export function useHydrateGrid< + P extends DehydratedDashboardPanelProps = DehydratedDashboardPanelProps, +>(): PanelHydrateFunction< + P, + P & Pick +> { const dh = useApi(); const connection = useConnection(); const loadPlugin = useLoadTablePlugin(); const hydrate = useCallback( - (hydrateProps: DehydratedDashboardPanelProps, id: string) => { + (hydrateProps: P, id: string) => { let metadata: IrisGridPanelMetadata; if (isIrisGridPanelMetadata(hydrateProps.metadata)) { metadata = hydrateProps.metadata; diff --git a/packages/dashboard/CHANGELOG.md b/packages/dashboard/CHANGELOG.md index 7d1c1a7b95..f733824ca4 100644 --- a/packages/dashboard/CHANGELOG.md +++ b/packages/dashboard/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/dashboard + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) diff --git a/packages/dashboard/package.json b/packages/dashboard/package.json index 4559747be6..e6e67d8245 100644 --- a/packages/dashboard/package.json +++ b/packages/dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/dashboard", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven Dashboard", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", @@ -38,6 +38,7 @@ "peerDependencies": { "react": "^17.0.0", "react-dom": "^17.0.0", + "react-is": "^17.0.0", "react-redux": "^7.2.4" }, "devDependencies": { diff --git a/packages/dashboard/src/DashboardLayout.tsx b/packages/dashboard/src/DashboardLayout.tsx index 2b5aa80492..d7b899958a 100644 --- a/packages/dashboard/src/DashboardLayout.tsx +++ b/packages/dashboard/src/DashboardLayout.tsx @@ -21,6 +21,7 @@ import PanelManager, { ClosedPanels } from './PanelManager'; import PanelErrorBoundary from './PanelErrorBoundary'; import LayoutUtils from './layout/LayoutUtils'; import { + canHaveRef, dehydrate as dehydrateDefault, hydrate as hydrateDefault, } from './DashboardUtils'; @@ -28,7 +29,6 @@ import PanelEvent from './PanelEvent'; import { GLPropTypes, useListener } from './layout'; import { getDashboardData, updateDashboardData } from './redux'; import { - isWrappedComponent, PanelComponentType, PanelDehydrateFunction, PanelHydrateFunction, @@ -127,18 +127,12 @@ export function DashboardLayout({ const CType = componentType as any; const PanelWrapperType = panelWrapper; - /* - Checking for class components will let us silence the React warning - about assigning refs to function components not using forwardRef. - The ref is used to detect changes to class component state so we - can track changes to panelState. We should opt for more explicit - state changes in the future and in functional components. - */ - const isClassComponent = - (isWrappedComponent(CType) && - CType.WrappedComponent.prototype != null && - CType.WrappedComponent.prototype.isReactComponent != null) || - (CType.prototype != null && CType.prototype.isReactComponent != null); + /** + * The ref is used to detect changes to class component state so we + * can track changes to panelState. We should opt for more explicit + * state changes in the future and in functional components. + */ + const hasRef = canHaveRef(CType); // Props supplied by GoldenLayout const { glContainer, glEventHub } = props; @@ -146,7 +140,7 @@ export function DashboardLayout({ {/* eslint-disable-next-line react/jsx-props-no-spreading */} - {isClassComponent ? ( + {hasRef ? ( // eslint-disable-next-line react/jsx-props-no-spreading ) : ( @@ -158,6 +152,10 @@ export function DashboardLayout({ ); } + wrappedComponent.displayName = `DashboardWrapper(${ + componentType.displayName ?? name + })`; + const cleanup = layout.registerComponent( name, React.forwardRef(wrappedComponent) diff --git a/packages/dashboard/src/DashboardUtils.test.tsx b/packages/dashboard/src/DashboardUtils.test.tsx new file mode 100644 index 0000000000..10c032d991 --- /dev/null +++ b/packages/dashboard/src/DashboardUtils.test.tsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { canHaveRef } from './DashboardUtils'; +import { type PanelProps } from './DashboardPlugin'; + +test('canHaveRef', () => { + function TestComponent() { + return
Test
; + } + + class TestClass extends React.PureComponent { + render() { + return
Test
; + } + } + + expect(canHaveRef(TestComponent)).toBe(false); + expect(canHaveRef(React.forwardRef(TestComponent))).toBe(true); + expect(canHaveRef(TestClass)).toBe(true); + expect( + canHaveRef(connect(null, null, null, { forwardRef: true })(TestClass)) + ).toBe(true); +}); diff --git a/packages/dashboard/src/DashboardUtils.ts b/packages/dashboard/src/DashboardUtils.tsx similarity index 57% rename from packages/dashboard/src/DashboardUtils.ts rename to packages/dashboard/src/DashboardUtils.tsx index 815f39eecb..ccc8c0d088 100644 --- a/packages/dashboard/src/DashboardUtils.ts +++ b/packages/dashboard/src/DashboardUtils.tsx @@ -1,4 +1,10 @@ -import { DehydratedDashboardPanelProps, PanelConfig } from './DashboardPlugin'; +import { ForwardRef } from 'react-is'; +import { + DehydratedDashboardPanelProps, + isWrappedComponent, + PanelComponentType, + PanelConfig, +} from './DashboardPlugin'; /** * Dehydrate an existing panel to allow it to be serialized/saved. @@ -48,6 +54,29 @@ export function hydrate( }; } +/** + * Checks if a panel component can take a ref. Helps silence react dev errors + * if a ref is passed to a functional component without forwardRef. + * @param component The panel component to check if it can take a ref + * @returns Wheter the component can take a ref or not + */ +export function canHaveRef(component: PanelComponentType): boolean { + // Might be a redux connect wrapped component + const isClassComponent = + (isWrappedComponent(component) && + component.WrappedComponent.prototype != null && + component.WrappedComponent.prototype.isReactComponent != null) || + (component.prototype != null && + component.prototype.isReactComponent != null); + + const isForwardRef = + !isWrappedComponent(component) && + '$$typeof' in component && + component.$$typeof === ForwardRef; + + return isClassComponent || isForwardRef; +} + export default { dehydrate, hydrate, diff --git a/packages/embed-chart/CHANGELOG.md b/packages/embed-chart/CHANGELOG.md index 12f42d37cd..9b27839861 100644 --- a/packages/embed-chart/CHANGELOG.md +++ b/packages/embed-chart/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Features + +* Theme Plugin Loading ([#1524](https://github.com/deephaven/web-client-ui/issues/1524)) ([a9541b1](https://github.com/deephaven/web-client-ui/commit/a9541b108f1d998bb2713e70642f5a54aaf8bd97)), closes [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1530](https://github.com/deephaven/web-client-ui/issues/1530) + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) **Note:** Version bump only for package @deephaven/embed-chart diff --git a/packages/embed-chart/package.json b/packages/embed-chart/package.json index e5e3eb66df..d63eeb80ae 100644 --- a/packages/embed-chart/package.json +++ b/packages/embed-chart/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/embed-chart", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven Embedded Chart", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", @@ -30,7 +30,7 @@ "scripts": { "analyze": "source-map-explorer build/assets/*.js --no-border-checks", "start": "vite", - "build": "vite build", + "build": "NODE_OPTIONS='--max-old-space-size=4096' vite build", "preview": "vite preview" }, "devDependencies": { diff --git a/packages/embed-grid/CHANGELOG.md b/packages/embed-grid/CHANGELOG.md index 92ffc6dcc4..69ee659283 100644 --- a/packages/embed-grid/CHANGELOG.md +++ b/packages/embed-grid/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Features + +* Theme Plugin Loading ([#1524](https://github.com/deephaven/web-client-ui/issues/1524)) ([a9541b1](https://github.com/deephaven/web-client-ui/commit/a9541b108f1d998bb2713e70642f5a54aaf8bd97)), closes [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1530](https://github.com/deephaven/web-client-ui/issues/1530) + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) diff --git a/packages/embed-grid/package.json b/packages/embed-grid/package.json index 2d6785eb48..6b2b20056e 100644 --- a/packages/embed-grid/package.json +++ b/packages/embed-grid/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/embed-grid", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven Embedded Grid", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/eslint-config/CHANGELOG.md b/packages/eslint-config/CHANGELOG.md index edc97add21..8e77efde8d 100644 --- a/packages/eslint-config/CHANGELOG.md +++ b/packages/eslint-config/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/eslint-config + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/eslint-config diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index 5502532107..673b64c68b 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/eslint-config", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven ESLint configuration", "repository": { "type": "git", diff --git a/packages/file-explorer/CHANGELOG.md b/packages/file-explorer/CHANGELOG.md index 33f73d7fbc..8815a46a34 100644 --- a/packages/file-explorer/CHANGELOG.md +++ b/packages/file-explorer/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Bug Fixes + +* Handle deletion of unsaved copied file in NotebookPanel ([#1557](https://github.com/deephaven/web-client-ui/issues/1557)) ([4021aac](https://github.com/deephaven/web-client-ui/commit/4021aac3bc130f8eec84385c9aadcb4ecf0b995c)), closes [#1359](https://github.com/deephaven/web-client-ui/issues/1359) + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) **Note:** Version bump only for package @deephaven/file-explorer diff --git a/packages/file-explorer/package.json b/packages/file-explorer/package.json index 6c88007afe..2edca5b01c 100644 --- a/packages/file-explorer/package.json +++ b/packages/file-explorer/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/file-explorer", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven File Explorer React component", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/file-explorer/src/FileUtils.ts b/packages/file-explorer/src/FileUtils.ts index 6bae38bbb9..6acaae7f58 100644 --- a/packages/file-explorer/src/FileUtils.ts +++ b/packages/file-explorer/src/FileUtils.ts @@ -1,4 +1,6 @@ import { ValidationError } from '@deephaven/utils'; +import FileNotFoundError from './FileNotFoundError'; +import { FileStorage } from './FileStorage'; /** * A basic list of some common MIME types. @@ -16,6 +18,22 @@ export enum MIME_TYPE { * Collection of utils for operating on file names */ export class FileUtils { + static async fileExists( + fileStorage: FileStorage, + name: string + ): Promise { + try { + await fileStorage.info(name); + return true; + } catch (e) { + // Should probably make sure it's a `FileNotFoundError`, and re-throw the error if it is not + if (!(e instanceof FileNotFoundError)) { + throw e; + } + return false; + } + } + /** * Format file extension * @param extension File extension to format, defaults to empty string @@ -80,6 +98,19 @@ export class FileUtils { return extension !== null ? `${copyName}.${extension}` : copyName; } + static async getUniqueCopyFileName( + fileStorage: FileStorage, + originalName: string + ): Promise { + let copyName = FileUtils.getCopyFileName(originalName); + // await in loop is fine here, this isn't a parallel task + // eslint-disable-next-line no-await-in-loop + while (await FileUtils.fileExists(fileStorage, copyName)) { + copyName = FileUtils.getCopyFileName(copyName); + } + return copyName; + } + /** * Return a MIME type for the provided file * @param name The file name to get the type for diff --git a/packages/filters/CHANGELOG.md b/packages/filters/CHANGELOG.md index 0a3aa5ce6e..0ab2727f98 100644 --- a/packages/filters/CHANGELOG.md +++ b/packages/filters/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/filters + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/filters diff --git a/packages/filters/package.json b/packages/filters/package.json index 1f8021e1ba..dd76e56e05 100644 --- a/packages/filters/package.json +++ b/packages/filters/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/filters", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven Filters", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/golden-layout/CHANGELOG.md b/packages/golden-layout/CHANGELOG.md index 536a807677..0fa72692f4 100644 --- a/packages/golden-layout/CHANGELOG.md +++ b/packages/golden-layout/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +* fix!: CSS based loading spinner (#1532) ([f06fbb0](https://github.com/deephaven/web-client-ui/commit/f06fbb01e27eaaeccab6031d8ff010ffee303d99)), closes [#1532](https://github.com/deephaven/web-client-ui/issues/1532) [#1531](https://github.com/deephaven/web-client-ui/issues/1531) + + +### Features + +* Monaco theming ([#1560](https://github.com/deephaven/web-client-ui/issues/1560)) ([4eda17c](https://github.com/deephaven/web-client-ui/commit/4eda17c82f6c177a11ba600d6f43c4f36915f6bd)), closes [#1542](https://github.com/deephaven/web-client-ui/issues/1542) +* Theme Plugin Loading ([#1524](https://github.com/deephaven/web-client-ui/issues/1524)) ([a9541b1](https://github.com/deephaven/web-client-ui/commit/a9541b108f1d998bb2713e70642f5a54aaf8bd97)), closes [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1530](https://github.com/deephaven/web-client-ui/issues/1530) + + +### BREAKING CHANGES + +* Theme variables have to be present on body to avoid +Monaco init failing +* Inline LoadingSpinner instances will need to be +decorated with `className="loading-spinner-vertical-align"` for vertical +alignment to work as before + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) diff --git a/packages/golden-layout/package.json b/packages/golden-layout/package.json index d44720406d..58b863a4b8 100644 --- a/packages/golden-layout/package.json +++ b/packages/golden-layout/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/golden-layout", - "version": "0.49.1", + "version": "0.50.0", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", "description": "A multi-screen javascript Layout manager", diff --git a/packages/golden-layout/src/controls/Header.ts b/packages/golden-layout/src/controls/Header.ts index 7406bfd5f9..20af2378c4 100644 --- a/packages/golden-layout/src/controls/Header.ts +++ b/packages/golden-layout/src/controls/Header.ts @@ -214,7 +214,8 @@ export default class Header extends EventEmitter { // makes sure dropped tabs are scrollintoview, removed any re-ordering this.tabs[this.parent.config.activeItemIndex ?? 0].element .get(0) - ?.scrollIntoView({ + ?.scrollIntoView?.({ + // Optional chain scrollIntoView call so tests do not error inline: 'nearest', }); diff --git a/packages/grid/CHANGELOG.md b/packages/grid/CHANGELOG.md index 3569805493..dd8ac2465b 100644 --- a/packages/grid/CHANGELOG.md +++ b/packages/grid/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Features + +* data bar render from API ([#1415](https://github.com/deephaven/web-client-ui/issues/1415)) ([ee7d1c1](https://github.com/deephaven/web-client-ui/commit/ee7d1c108e86973b4c6855e482dce21d665dfe28)), closes [#0000](https://github.com/deephaven/web-client-ui/issues/0000) [#FF0000](https://github.com/deephaven/web-client-ui/issues/FF0000) [#FFFF00](https://github.com/deephaven/web-client-ui/issues/FFFF00) [#FFFF00](https://github.com/deephaven/web-client-ui/issues/FFFF00) [#00FF00](https://github.com/deephaven/web-client-ui/issues/00FF00) + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) diff --git a/packages/grid/package.json b/packages/grid/package.json index 8781faa097..a3c8c458bb 100644 --- a/packages/grid/package.json +++ b/packages/grid/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/grid", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven React grid component", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/grid/src/GridMetricCalculator.ts b/packages/grid/src/GridMetricCalculator.ts index e9c2a9f950..4b36b92589 100644 --- a/packages/grid/src/GridMetricCalculator.ts +++ b/packages/grid/src/GridMetricCalculator.ts @@ -1656,7 +1656,7 @@ export class GridMetricCalculator { treePaddingX: number = this.calculateTreePaddingX(state) ): number { const { theme } = state; - const { autoSizeColumns, minColumnWidth } = theme; + const { autoSizeColumns, minColumnWidth, maxColumnWidth } = theme; if (!autoSizeColumns) { const { columnWidth } = theme; return columnWidth; @@ -1667,6 +1667,7 @@ export class GridMetricCalculator { const cachedValue = this.calculatedColumnWidths.get(modelColumn); let columnWidth = Math.ceil(Math.max(headerWidth, dataWidth)); columnWidth = Math.max(minColumnWidth, columnWidth); + columnWidth = Math.min(maxColumnWidth, columnWidth); if (cachedValue != null && cachedValue > columnWidth) { columnWidth = cachedValue; } else { diff --git a/packages/grid/src/GridTheme.ts b/packages/grid/src/GridTheme.ts index df3c55a2a3..13e4137c53 100644 --- a/packages/grid/src/GridTheme.ts +++ b/packages/grid/src/GridTheme.ts @@ -105,6 +105,7 @@ export type GridTheme = { columnWidth: number; minRowHeight: number; minColumnWidth: number; + maxColumnWidth: number; // Default row/column header/footers width/height columnHeaderHeight: number; @@ -206,6 +207,7 @@ const defaultTheme: GridTheme = Object.freeze({ columnWidth: 100, minRowHeight: 20, minColumnWidth: 55, + maxColumnWidth: 600, columnHeaderHeight: 20, rowHeaderWidth: 30, rowFooterWidth: 0, diff --git a/packages/icons/CHANGELOG.md b/packages/icons/CHANGELOG.md index 8206b60207..ac7348edda 100644 --- a/packages/icons/CHANGELOG.md +++ b/packages/icons/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/icons + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/icons diff --git a/packages/icons/package.json b/packages/icons/package.json index c3397ad0dc..296d9fa492 100644 --- a/packages/icons/package.json +++ b/packages/icons/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/icons", - "version": "0.49.0", + "version": "0.50.0", "description": "Icons used in Deephaven client apps. Extends vscode-codicons to be font-awesome svg-core compatible and adds additional icons in a similar style.", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/iris-grid/CHANGELOG.md b/packages/iris-grid/CHANGELOG.md index 760d84233f..69f113e833 100644 --- a/packages/iris-grid/CHANGELOG.md +++ b/packages/iris-grid/CHANGELOG.md @@ -3,6 +3,32 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Bug Fixes + +* Change display of rollup key columns from null to empty string ([#1563](https://github.com/deephaven/web-client-ui/issues/1563)) ([327bcb6](https://github.com/deephaven/web-client-ui/commit/327bcb649d47bff648a71fd7f979a63094650b25)), closes [#1483](https://github.com/deephaven/web-client-ui/issues/1483) + + +* fix!: CSS based loading spinner (#1532) ([f06fbb0](https://github.com/deephaven/web-client-ui/commit/f06fbb01e27eaaeccab6031d8ff010ffee303d99)), closes [#1532](https://github.com/deephaven/web-client-ui/issues/1532) [#1531](https://github.com/deephaven/web-client-ui/issues/1531) + + +### Features + +* data bar render from API ([#1415](https://github.com/deephaven/web-client-ui/issues/1415)) ([ee7d1c1](https://github.com/deephaven/web-client-ui/commit/ee7d1c108e86973b4c6855e482dce21d665dfe28)), closes [#0000](https://github.com/deephaven/web-client-ui/issues/0000) [#FF0000](https://github.com/deephaven/web-client-ui/issues/FF0000) [#FFFF00](https://github.com/deephaven/web-client-ui/issues/FFFF00) [#FFFF00](https://github.com/deephaven/web-client-ui/issues/FFFF00) [#00FF00](https://github.com/deephaven/web-client-ui/issues/00FF00) + + +### BREAKING CHANGES + +* Inline LoadingSpinner instances will need to be +decorated with `className="loading-spinner-vertical-align"` for vertical +alignment to work as before + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) diff --git a/packages/iris-grid/package.json b/packages/iris-grid/package.json index a8c3fd17e4..0aa0decd93 100644 --- a/packages/iris-grid/package.json +++ b/packages/iris-grid/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/iris-grid", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven Iris Grid", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/iris-grid/src/IrisGrid.tsx b/packages/iris-grid/src/IrisGrid.tsx index a190b2c6a3..90fcb670d8 100644 --- a/packages/iris-grid/src/IrisGrid.tsx +++ b/packages/iris-grid/src/IrisGrid.tsx @@ -131,7 +131,7 @@ import ToastBottomBar from './ToastBottomBar'; import IrisGridMetricCalculator from './IrisGridMetricCalculator'; import IrisGridModelUpdater from './IrisGridModelUpdater'; import IrisGridRenderer from './IrisGridRenderer'; -import IrisGridTheme, { IrisGridThemeType } from './IrisGridTheme'; +import { createDefaultIrisGridTheme, IrisGridThemeType } from './IrisGridTheme'; import ColumnStatistics from './ColumnStatistics'; import './IrisGrid.scss'; import AdvancedFilterCreator from './AdvancedFilterCreator'; @@ -511,7 +511,7 @@ export class IrisGrid extends Component { canCopy: true, canDownloadCsv: true, frozenColumns: null, - theme: IrisGridTheme, + theme: null, canToggleSearch: true, }; @@ -1341,16 +1341,25 @@ export class IrisGrid extends Component { getCachedTheme = memoize( ( - theme: GridThemeType, + theme: GridThemeType | null, isEditable: boolean, floatingRowCount: number - ): Partial => ({ - ...IrisGridTheme, - ...theme, - autoSelectRow: !isEditable, + ): Partial => { + const defaultTheme = createDefaultIrisGridTheme(); + // We only show the row footers when we have floating rows for aggregations - rowFooterWidth: floatingRowCount > 0 ? theme.rowFooterWidth : 0, - }), + const rowFooterWidth = + floatingRowCount > 0 + ? theme?.rowFooterWidth ?? defaultTheme.rowFooterWidth + : 0; + + return { + ...defaultTheme, + ...theme, + autoSelectRow: !isEditable, + rowFooterWidth, + }; + }, { max: 1 } ); diff --git a/packages/iris-grid/src/IrisGridTheme.module.scss b/packages/iris-grid/src/IrisGridTheme.module.scss index 41e50c5799..a74d9c267e 100644 --- a/packages/iris-grid/src/IrisGridTheme.module.scss +++ b/packages/iris-grid/src/IrisGridTheme.module.scss @@ -1,103 +1,98 @@ /* stylelint-disable */ @import '@deephaven/components/scss/custom.scss'; -$selection-color: rgba($blue, 0.09); $selection-outline-color: $blue; -$selection-outline-casing-color: $gray-900; $font-size: 12px; $row-height: 19px; -$row-hover-bg: mix($gray-600, $gray-700, 50%); $header-bg: $content-bg; $header-separator-color: $gray-900; $header-height: 30px; :export { - grid-bg: $gray-900; + grid-bg: var(--dh-color-grid-bg); font: $font-size Fira Sans, sans-serif; // must be preloaded - white: $white; - black: $black; - header-bg: $header-bg; - header-color: $foreground; + white: var(--dh-color-white); + black: var(--dh-color-black); + header-bg: var(--dh-color-grid-header-bg); + header-color: var(--dh-color-grid-header-text); header-height: $header-height; - header-separator-color: $header-separator-color; - header-separator-hover-color: $gray-400; - header-hidden-separator-hover-color: $primary; - header-sort-bar-color: $purple; - header-reverse-bar-color: $green-dark; - header-bar-casing-color: $gray-900; + header-separator-color: var(--dh-color-grid-header-separator); + header-separator-hover-color: var(--dh-color-grid-header-separator-hover); + header-hidden-separator-hover-color: var( + --dh-color-grid-header-separator-hidden-hover + ); + header-sort-bar-color: var(--dh-color-grid-header-sort-bar); + header-reverse-bar-color: var(--dh-color-grid-header-reverse-bar); + header-bar-casing-color: var(--dh-color-grid-header-bar-casing); header-font: 600 $font-size Fira Sans, sans-serif; // must be preloaded row-height: $row-height; - row-background-colors: $gray-800 $content-bg; - selection-color: $selection-color; - selection-outline-color: $selection-outline-color; - selection-outline-casing-color: $selection-outline-casing-color; - row-hover-bg: $row-hover-bg; - selected-row-hover-bg: rgba($blue, 0.25); - scroll-bar-active-selection-tick-color: rgba($blue, 0.5); + row-background-colors: var(--dh-color-grid-row-0-bg) + var(--dh-color-grid-row-1-bg); + selection-color: var(--dh-color-grid-selection); + selection-outline-color: var(--dh-color-grid-selection-outline); + selection-outline-casing-color: var(--dh-color-grid-selection-outline-casing); + row-hover-bg: var(--dh-color-grid-row-hover-bg); + selected-row-hover-bg: var(--dh-color-grid-row-hover-bg-selected); + scroll-bar-active-selection-tick-color: var( + --dh-color-grid-scroll-bar-active-selection-tick + ); - scroll-bar-bg: $gray-850; - scroll-bar-hover-bg: $gray-800; - scroll-bar-casing-color: $gray-600; - scroll-bar-corner-color: $gray-850; - scroll-bar-color: $gray-500; - scroll-bar-hover-color: $gray-400; - scroll-bar-active-color: $gray-300; + scroll-bar-bg: var(--dh-color-grid-scroll-bar-bg); + scroll-bar-hover-bg: var(--dh-color-grid-scroll-bar-hover-bg); + scroll-bar-casing-color: var(--dh-color-grid-scroll-bar-casing); + scroll-bar-corner-color: var(--dh-color-grid-scroll-bar-corner); + scroll-bar-color: var(--dh-color-grid-scroll-bar); + scroll-bar-hover-color: var(--dh-color-grid-scroll-bar-hover); + scroll-bar-active-color: var(--dh-color-grid-scroll-bar-active); - text-color: $white; - hyperlink-color: $primary; - positive-number-color: $green; - negative-number-color: $red; - zero-number-color: $yellow; - date-color: $yellow; - pending-text-color: lighten($yellow, 10%); - error-text-color: $danger; - null-string-color: $gray-400; + text-color: var(--dh-color-grid-text); + hyperlink-color: var(--dh-color-grid-text-hyperlink); + positive-number-color: var(--dh-color-grid-number-positive); + negative-number-color: var(--dh-color-grid-number-negative); + zero-number-color: var(--dh-color-grid-number-zero); + date-color: var(--dh-color-grid-date); + pending-text-color: var(--dh-color-grid-text-pending); + error-text-color: var(--dh-color-grid-text-error); + null-string-color: var(--dh-color-grid-string-null); - $filter-color: $primary; // local to just the following - filter-bar-active-bg: scale-color( - $filter-color, - $saturation: -65%, - $lightness: -40% + filter-bar-active-bg: var(--dh-color-grid-filter-bar-active-bg); + filter-bar-active-color: var(--dh-color-grid-filter-bar-active); + filter-bar-expanded-bg: var(--dh-color-grid-filter-bar-expanded-bg); + filter-bar-expanded-active-bg: var( + --dh-color-grid-filter-bar-expanded-active-bg ); - filter-bar-active-color: $filter-color; - filter-bar-expanded-bg: $gray-800; - filter-bar-expanded-active-bg: scale-color( - $filter-color, - $saturation: -75%, - $lightness: -60% + filter-bar-expanded-active-cell-bg: var( + --dh-color-grid-filter-bar-expanded-active-cell-bg ); - filter-bar-expanded-active-cell-bg: scale-color( - $filter-color, - $saturation: -50%, - $lightness: -40% - ); - filter-bar-separator-color: $gray-400; - filter-bar-error-color: $danger; - filter-icon-color: $filter-color; + filter-bar-separator-color: var(--dh-color-grid-filter-bar-separator); + filter-bar-error-color: var(--dh-color-grid-filter-bar-error); + filter-icon-color: var(--dh-color-grid-filter-icon); - scrim-color: $gray-900; - context-menu-sort-icon-color: $purple; - context-menu-reverse-icon-color: $green-dark; - linker-column-hover-bg: rgba($blue, 0.09); - tree-line-color: $gray-500; - tree-marker-color: $gray-300; - tree-marker-hover-color: $gray-100; - grouped-column-divider-color: $black; + scrim-color: var(--dh-color-grid-scrim); + context-menu-sort-icon-color: var(--dh-color-grid-context-menu-sort-icon); + context-menu-reverse-icon-color: var( + --dh-color-grid-context-menu-reverse-icon + ); + linker-column-hover-bg: var(--dh-color-grid-column-linker-hover-bg); + tree-line-color: var(--dh-color-grid-tree-line); + tree-marker-color: var(--dh-color-grid-tree-marker); + tree-marker-hover-color: var(--dh-color-grid-tree-marker-hover); + grouped-column-divider-color: var(--dh-color-grid-column-grouped-divider); - floating-grid-row-color: $gray-600; - floating-row-background-colors: $gray-700; - floating-divider-inner-color: $gray-700; - floating-divider-outer-color: $gray-900; + floating-grid-row-color: var(--dh-color-grid-floating-row); + floating-row-background-colors: var(--dh-color-grid-floating-row-bg); + floating-divider-inner-color: var(--dh-color-grid-floating-divider-inner); + floating-divider-outer-color: var(--dh-color-grid-floating-divider-outer); - overflow-button-color: $gray-300; - overflow-button-hover-color: $gray-100; + overflow-button-color: var(--dh-color-grid-overflow-button); + overflow-button-hover-color: var(--dh-color-grid-overflow-button-hover); - zero-line-color: $gray-500; - positive-bar-color: $green; - negative-bar-color: $red; - marker-bar-color: $white; + zero-line-color: var(--dh-color-grid-data-bar-zero-line); + positive-bar-color: var(--dh-color-grid-data-bar-positive); + negative-bar-color: var(--dh-color-grid-data-bar-negative); + marker-bar-color: var(--dh-color-grid-data-bar-marker); } diff --git a/packages/iris-grid/src/IrisGridTheme.test.ts b/packages/iris-grid/src/IrisGridTheme.test.ts new file mode 100644 index 0000000000..4bb745df15 --- /dev/null +++ b/packages/iris-grid/src/IrisGridTheme.test.ts @@ -0,0 +1,39 @@ +import { resolveCssVariablesInRecord } from '@deephaven/components'; +import { TestUtils } from '@deephaven/utils'; +import { createDefaultIrisGridTheme } from './IrisGridTheme'; + +const { asMock } = TestUtils; + +jest.mock('@deephaven/components', () => ({ + ...jest.requireActual('@deephaven/components'), + resolveCssVariablesInRecord: jest.fn(), +})); + +beforeEach(() => { + jest.clearAllMocks(); + expect.hasAssertions(); +}); + +describe('createDefaultIrisGridTheme', () => { + // Proxy for IrisGridTheme + const identityProxy = new Proxy( + {}, + { + get(_target, name) { + return `IrisGridTheme['${String(name)}']`; + }, + } + ); + + beforeEach(() => { + asMock(resolveCssVariablesInRecord) + .mockName('resolveCssVariablesInRecord') + .mockReturnValue(identityProxy); + }); + + it('should derive the default Iris grid theme', () => { + const theme = createDefaultIrisGridTheme(); + expect(resolveCssVariablesInRecord).toHaveBeenCalled(); + expect(theme).toMatchSnapshot(); + }); +}); diff --git a/packages/iris-grid/src/IrisGridTheme.ts b/packages/iris-grid/src/IrisGridTheme.ts index 1d3423fe6a..500dbf6ea3 100644 --- a/packages/iris-grid/src/IrisGridTheme.ts +++ b/packages/iris-grid/src/IrisGridTheme.ts @@ -1,6 +1,10 @@ +import { resolveCssVariablesInRecord } from '@deephaven/components'; import type { GridThemeType } from '@deephaven/grid'; +import Log from '@deephaven/log'; import { GridColor, NullableGridColor } from '@deephaven/grid/src/GridTheme'; -import IrisGridTheme from './IrisGridTheme.module.scss'; +import IrisGridThemeRaw from './IrisGridTheme.module.scss'; + +const log = Log.module('IrisGridTheme'); export type IrisGridThemeType = GridThemeType & { filterBarCollapsedHeight: number; @@ -39,107 +43,120 @@ export type IrisGridThemeType = GridThemeType & { floatingGridRowColor: NullableGridColor; }; -const theme: Partial = Object.freeze({ - backgroundColor: IrisGridTheme['grid-bg'], - white: IrisGridTheme.white, - black: IrisGridTheme.black, - font: IrisGridTheme.font, - headerBackgroundColor: IrisGridTheme['header-bg'], - headerColor: IrisGridTheme['header-color'], - headerSeparatorColor: IrisGridTheme['header-separator-color'], - headerSeparatorHoverColor: IrisGridTheme['header-separator-hover-color'], - headerHiddenSeparatorHoverColor: - IrisGridTheme['header-hidden-separator-hover-color'], - headerSortBarColor: IrisGridTheme['header-sort-bar-color'], - headerReverseBarColor: IrisGridTheme['header-reverse-bar-color'], - headerBarCasingColor: IrisGridTheme['header-bar-casing-color'], - headerFont: IrisGridTheme['header-font'], - rowBackgroundColors: IrisGridTheme['row-background-colors'], - rowHoverBackgroundColor: IrisGridTheme['row-hover-bg'], - selectionColor: IrisGridTheme['selection-color'], - selectionOutlineColor: IrisGridTheme['selection-outline-color'], - selectionOutlineCasingColor: IrisGridTheme['selection-outline-casing-color'], - selectedRowHoverBackgroundColor: IrisGridTheme['selected-row-hover-bg'], - scrollBarBackgroundColor: IrisGridTheme['scroll-bar-bg'], - scrollBarHoverBackgroundColor: IrisGridTheme['scroll-bar-hover-bg'], - scrollBarCasingColor: IrisGridTheme['scroll-bar-casing-color'], - scrollBarCornerColor: IrisGridTheme['scroll-bar-corner-color'], - scrollBarColor: IrisGridTheme['scroll-bar-color'], - scrollBarHoverColor: IrisGridTheme['scroll-bar-hover-color'], - scrollBarActiveColor: IrisGridTheme['scroll-bar-active-color'], - scrollBarSelectionTickColor: IrisGridTheme['selected-row-hover-bg'], - scrollBarActiveSelectionTickColor: - IrisGridTheme['scroll-bar-active-selection-tick-color'], - textColor: IrisGridTheme['text-color'], - hyperlinkColor: IrisGridTheme['hyperlink-color'], - positiveNumberColor: IrisGridTheme['positive-number-color'], - negativeNumberColor: IrisGridTheme['negative-number-color'], - zeroNumberColor: IrisGridTheme['zero-number-color'], - dateColor: IrisGridTheme['date-color'], - pendingTextColor: IrisGridTheme['pending-text-color'], - errorTextColor: IrisGridTheme['error-text-color'], - nullStringColor: IrisGridTheme['null-string-color'], - filterBarActiveBackgroundColor: IrisGridTheme['filter-bar-active-bg'], - filterBarExpandedBackgroundColor: IrisGridTheme['filter-bar-expanded-bg'], - filterBarExpandedActiveBackgroundColor: - IrisGridTheme['filter-bar-expanded-active-bg'], - filterBarExpandedActiveCellBackgroundColor: - IrisGridTheme['filter-bar-expanded-active-cell-bg'], - filterBarSeparatorColor: IrisGridTheme['filter-bar-separator-color'], - filterBarActiveColor: IrisGridTheme['filter-bar-active-color'], - filterBarErrorColor: IrisGridTheme['filter-bar-error-color'], - filterIconColor: IrisGridTheme['filter-icon-color'], - scrimColor: IrisGridTheme['scrim-color'], - contextMenuSortIconColor: IrisGridTheme['context-menu-sort-icon-color'], - contextMenuReverseIconColor: IrisGridTheme['context-menu-reverse-icon-color'], +/** + * Derive default Iris grid theme from IrisGridThemeRaw. Note that CSS variables + * contained in IrisGridThemeRaw are resolved to their actual values. This means + * that the returned theme is statically defined and does not change when CSS + * variables change. + */ +export function createDefaultIrisGridTheme(): Partial { + const IrisGridTheme = resolveCssVariablesInRecord(IrisGridThemeRaw); + log.debug2('Iris grid theme:', IrisGridThemeRaw); + log.debug2('Iris grid theme derived:', IrisGridTheme); - allowRowResize: false, - autoSelectRow: true, - gridColumnColor: null, - gridRowColor: null, - groupedColumnDividerColor: IrisGridTheme['grouped-column-divider-color'], - columnHoverBackgroundColor: null, - headerHorizontalPadding: 12, - scrollBarSize: 13, - scrollBarHoverSize: 16, // system default scrollbar width is 17 - minScrollHandleSize: 24, - rowHeight: parseInt(IrisGridTheme['row-height'], 10) || 19, // IrisGrid test breaks without the fallback value - columnWidth: 100, - rowHeaderWidth: 0, - rowFooterWidth: 60, - columnHeaderHeight: parseInt(IrisGridTheme['header-height'], 10) || 30, - filterBarHeight: 30, // includes 1px casing at bottom - filterBarCollapsedHeight: 5, // includes 1px casing at bottom - sortHeaderBarHeight: 2, - reverseHeaderBarHeight: 4, - filterBarHorizontalPadding: 4, + return Object.freeze({ + backgroundColor: IrisGridTheme['grid-bg'], + white: IrisGridTheme.white, + black: IrisGridTheme.black, + font: IrisGridTheme.font, + headerBackgroundColor: IrisGridTheme['header-bg'], + headerColor: IrisGridTheme['header-color'], + headerSeparatorColor: IrisGridTheme['header-separator-color'], + headerSeparatorHoverColor: IrisGridTheme['header-separator-hover-color'], + headerHiddenSeparatorHoverColor: + IrisGridTheme['header-hidden-separator-hover-color'], + headerSortBarColor: IrisGridTheme['header-sort-bar-color'], + headerReverseBarColor: IrisGridTheme['header-reverse-bar-color'], + headerBarCasingColor: IrisGridTheme['header-bar-casing-color'], + headerFont: IrisGridTheme['header-font'], + rowBackgroundColors: IrisGridTheme['row-background-colors'], + rowHoverBackgroundColor: IrisGridTheme['row-hover-bg'], + selectionColor: IrisGridTheme['selection-color'], + selectionOutlineColor: IrisGridTheme['selection-outline-color'], + selectionOutlineCasingColor: + IrisGridTheme['selection-outline-casing-color'], + selectedRowHoverBackgroundColor: IrisGridTheme['selected-row-hover-bg'], + scrollBarBackgroundColor: IrisGridTheme['scroll-bar-bg'], + scrollBarHoverBackgroundColor: IrisGridTheme['scroll-bar-hover-bg'], + scrollBarCasingColor: IrisGridTheme['scroll-bar-casing-color'], + scrollBarCornerColor: IrisGridTheme['scroll-bar-corner-color'], + scrollBarColor: IrisGridTheme['scroll-bar-color'], + scrollBarHoverColor: IrisGridTheme['scroll-bar-hover-color'], + scrollBarActiveColor: IrisGridTheme['scroll-bar-active-color'], + scrollBarSelectionTickColor: IrisGridTheme['selected-row-hover-bg'], + scrollBarActiveSelectionTickColor: + IrisGridTheme['scroll-bar-active-selection-tick-color'], + textColor: IrisGridTheme['text-color'], + hyperlinkColor: IrisGridTheme['hyperlink-color'], + positiveNumberColor: IrisGridTheme['positive-number-color'], + negativeNumberColor: IrisGridTheme['negative-number-color'], + zeroNumberColor: IrisGridTheme['zero-number-color'], + dateColor: IrisGridTheme['date-color'], + pendingTextColor: IrisGridTheme['pending-text-color'], + errorTextColor: IrisGridTheme['error-text-color'], + nullStringColor: IrisGridTheme['null-string-color'], + filterBarActiveBackgroundColor: IrisGridTheme['filter-bar-active-bg'], + filterBarExpandedBackgroundColor: IrisGridTheme['filter-bar-expanded-bg'], + filterBarExpandedActiveBackgroundColor: + IrisGridTheme['filter-bar-expanded-active-bg'], + filterBarExpandedActiveCellBackgroundColor: + IrisGridTheme['filter-bar-expanded-active-cell-bg'], + filterBarSeparatorColor: IrisGridTheme['filter-bar-separator-color'], + filterBarActiveColor: IrisGridTheme['filter-bar-active-color'], + filterBarErrorColor: IrisGridTheme['filter-bar-error-color'], + filterIconColor: IrisGridTheme['filter-icon-color'], + scrimColor: IrisGridTheme['scrim-color'], + contextMenuSortIconColor: IrisGridTheme['context-menu-sort-icon-color'], + contextMenuReverseIconColor: + IrisGridTheme['context-menu-reverse-icon-color'], - // Amount of blur to apply to the bottom of the scrim while animating in - scrimBlurSize: 25, - minScrimTransitionTime: 150, - maxScrimTransitionTime: 350, + allowRowResize: false, + autoSelectRow: true, + gridColumnColor: null, + gridRowColor: null, + groupedColumnDividerColor: IrisGridTheme['grouped-column-divider-color'], + columnHoverBackgroundColor: null, + headerHorizontalPadding: 12, + scrollBarSize: 13, + scrollBarHoverSize: 16, // system default scrollbar width is 17 + minScrollHandleSize: 24, + rowHeight: parseInt(IrisGridTheme['row-height'], 10) || 19, // IrisGrid test breaks without the fallback value + columnWidth: 100, + rowHeaderWidth: 0, + rowFooterWidth: 60, + columnHeaderHeight: parseInt(IrisGridTheme['header-height'], 10) || 30, + filterBarHeight: 30, // includes 1px casing at bottom + filterBarCollapsedHeight: 5, // includes 1px casing at bottom + sortHeaderBarHeight: 2, + reverseHeaderBarHeight: 4, + filterBarHorizontalPadding: 4, - scrollSnapToRow: true, + // Amount of blur to apply to the bottom of the scrim while animating in + scrimBlurSize: 25, + minScrimTransitionTime: 150, + maxScrimTransitionTime: 350, - linkerColumnHoverBackgroundColor: IrisGridTheme['linker-column-hover-bg'], + scrollSnapToRow: true, - treeLineColor: IrisGridTheme['tree-line-color'], - treeMarkerColor: IrisGridTheme['tree-marker-color'], - treeMarkerHoverColor: IrisGridTheme['tree-marker-hover-color'], + linkerColumnHoverBackgroundColor: IrisGridTheme['linker-column-hover-bg'], - floatingGridColumnColor: null, - floatingGridRowColor: IrisGridTheme['floating-grid-row-color'], - floatingRowBackgroundColors: IrisGridTheme['floating-row-background-colors'], - floatingDividerInnerColor: IrisGridTheme['floating-divider-inner-color'], - floatingDividerOuterColor: IrisGridTheme['floating-divider-outer-color'], + treeLineColor: IrisGridTheme['tree-line-color'], + treeMarkerColor: IrisGridTheme['tree-marker-color'], + treeMarkerHoverColor: IrisGridTheme['tree-marker-hover-color'], - overflowButtonColor: IrisGridTheme['overflow-button-color'], - overflowButtonHoverColor: IrisGridTheme['overflow-button-hover-color'], + floatingGridColumnColor: null, + floatingGridRowColor: IrisGridTheme['floating-grid-row-color'], + floatingRowBackgroundColors: + IrisGridTheme['floating-row-background-colors'], + floatingDividerInnerColor: IrisGridTheme['floating-divider-inner-color'], + floatingDividerOuterColor: IrisGridTheme['floating-divider-outer-color'], - zeroLineColor: IrisGridTheme['zero-line-color'], - positiveBarColor: IrisGridTheme['positive-bar-color'], - negativeBarColor: IrisGridTheme['negative-bar-color'], - markerBarColor: IrisGridTheme['marker-bar-color'], -}); + overflowButtonColor: IrisGridTheme['overflow-button-color'], + overflowButtonHoverColor: IrisGridTheme['overflow-button-hover-color'], -export default theme; + zeroLineColor: IrisGridTheme['zero-line-color'], + positiveBarColor: IrisGridTheme['positive-bar-color'], + negativeBarColor: IrisGridTheme['negative-bar-color'], + markerBarColor: IrisGridTheme['marker-bar-color'], + }); +} diff --git a/packages/iris-grid/src/IrisGridTreeTableModel.ts b/packages/iris-grid/src/IrisGridTreeTableModel.ts index 555cf140c8..003d58177c 100644 --- a/packages/iris-grid/src/IrisGridTreeTableModel.ts +++ b/packages/iris-grid/src/IrisGridTreeTableModel.ts @@ -33,6 +33,15 @@ class IrisGridTreeTableModel extends IrisGridTableModelTemplate< const value = this.valueForCell(x, y); return this.displayString(value, column.constituentType, column.name); } + // Show empty string instead of null in rollup grouping columns (issue #1483) + if ( + row.hasChildren && + row.depth <= x + 1 && + this.valueForCell(x, y) === null && + this.getCachedGroupedColumnSet(this.groupedColumns).has(x) + ) { + return ''; + } } return super.textForCell(x, y); @@ -182,6 +191,15 @@ class IrisGridTreeTableModel extends IrisGridTableModelTemplate< ) ); + getCachedGroupedColumnSet = memoize( + (groupedColumns: readonly Column[]) => + new Set( + groupedColumns.map(c1 => + this.columns.findIndex(c2 => c1.name === c2.name) + ) + ) + ); + updateFrozenColumns(columns: ColumnName[]): void { if (columns.length > 0) { throw new Error('Cannot freeze columns on a tree table'); diff --git a/packages/iris-grid/src/__snapshots__/IrisGridTheme.test.ts.snap b/packages/iris-grid/src/__snapshots__/IrisGridTheme.test.ts.snap new file mode 100644 index 0000000000..7a2e0cc4d5 --- /dev/null +++ b/packages/iris-grid/src/__snapshots__/IrisGridTheme.test.ts.snap @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`createDefaultIrisGridTheme should derive the default Iris grid theme 1`] = ` +{ + "allowRowResize": false, + "autoSelectRow": true, + "backgroundColor": "IrisGridTheme['grid-bg']", + "black": "IrisGridTheme['black']", + "columnHeaderHeight": 30, + "columnHoverBackgroundColor": null, + "columnWidth": 100, + "contextMenuReverseIconColor": "IrisGridTheme['context-menu-reverse-icon-color']", + "contextMenuSortIconColor": "IrisGridTheme['context-menu-sort-icon-color']", + "dateColor": "IrisGridTheme['date-color']", + "errorTextColor": "IrisGridTheme['error-text-color']", + "filterBarActiveBackgroundColor": "IrisGridTheme['filter-bar-active-bg']", + "filterBarActiveColor": "IrisGridTheme['filter-bar-active-color']", + "filterBarCollapsedHeight": 5, + "filterBarErrorColor": "IrisGridTheme['filter-bar-error-color']", + "filterBarExpandedActiveBackgroundColor": "IrisGridTheme['filter-bar-expanded-active-bg']", + "filterBarExpandedActiveCellBackgroundColor": "IrisGridTheme['filter-bar-expanded-active-cell-bg']", + "filterBarExpandedBackgroundColor": "IrisGridTheme['filter-bar-expanded-bg']", + "filterBarHeight": 30, + "filterBarHorizontalPadding": 4, + "filterBarSeparatorColor": "IrisGridTheme['filter-bar-separator-color']", + "filterIconColor": "IrisGridTheme['filter-icon-color']", + "floatingDividerInnerColor": "IrisGridTheme['floating-divider-inner-color']", + "floatingDividerOuterColor": "IrisGridTheme['floating-divider-outer-color']", + "floatingGridColumnColor": null, + "floatingGridRowColor": "IrisGridTheme['floating-grid-row-color']", + "floatingRowBackgroundColors": "IrisGridTheme['floating-row-background-colors']", + "font": "IrisGridTheme['font']", + "gridColumnColor": null, + "gridRowColor": null, + "groupedColumnDividerColor": "IrisGridTheme['grouped-column-divider-color']", + "headerBackgroundColor": "IrisGridTheme['header-bg']", + "headerBarCasingColor": "IrisGridTheme['header-bar-casing-color']", + "headerColor": "IrisGridTheme['header-color']", + "headerFont": "IrisGridTheme['header-font']", + "headerHiddenSeparatorHoverColor": "IrisGridTheme['header-hidden-separator-hover-color']", + "headerHorizontalPadding": 12, + "headerReverseBarColor": "IrisGridTheme['header-reverse-bar-color']", + "headerSeparatorColor": "IrisGridTheme['header-separator-color']", + "headerSeparatorHoverColor": "IrisGridTheme['header-separator-hover-color']", + "headerSortBarColor": "IrisGridTheme['header-sort-bar-color']", + "hyperlinkColor": "IrisGridTheme['hyperlink-color']", + "linkerColumnHoverBackgroundColor": "IrisGridTheme['linker-column-hover-bg']", + "markerBarColor": "IrisGridTheme['marker-bar-color']", + "maxScrimTransitionTime": 350, + "minScrimTransitionTime": 150, + "minScrollHandleSize": 24, + "negativeBarColor": "IrisGridTheme['negative-bar-color']", + "negativeNumberColor": "IrisGridTheme['negative-number-color']", + "nullStringColor": "IrisGridTheme['null-string-color']", + "overflowButtonColor": "IrisGridTheme['overflow-button-color']", + "overflowButtonHoverColor": "IrisGridTheme['overflow-button-hover-color']", + "pendingTextColor": "IrisGridTheme['pending-text-color']", + "positiveBarColor": "IrisGridTheme['positive-bar-color']", + "positiveNumberColor": "IrisGridTheme['positive-number-color']", + "reverseHeaderBarHeight": 4, + "rowBackgroundColors": "IrisGridTheme['row-background-colors']", + "rowFooterWidth": 60, + "rowHeaderWidth": 0, + "rowHeight": 19, + "rowHoverBackgroundColor": "IrisGridTheme['row-hover-bg']", + "scrimBlurSize": 25, + "scrimColor": "IrisGridTheme['scrim-color']", + "scrollBarActiveColor": "IrisGridTheme['scroll-bar-active-color']", + "scrollBarActiveSelectionTickColor": "IrisGridTheme['scroll-bar-active-selection-tick-color']", + "scrollBarBackgroundColor": "IrisGridTheme['scroll-bar-bg']", + "scrollBarCasingColor": "IrisGridTheme['scroll-bar-casing-color']", + "scrollBarColor": "IrisGridTheme['scroll-bar-color']", + "scrollBarCornerColor": "IrisGridTheme['scroll-bar-corner-color']", + "scrollBarHoverBackgroundColor": "IrisGridTheme['scroll-bar-hover-bg']", + "scrollBarHoverColor": "IrisGridTheme['scroll-bar-hover-color']", + "scrollBarHoverSize": 16, + "scrollBarSelectionTickColor": "IrisGridTheme['selected-row-hover-bg']", + "scrollBarSize": 13, + "scrollSnapToRow": true, + "selectedRowHoverBackgroundColor": "IrisGridTheme['selected-row-hover-bg']", + "selectionColor": "IrisGridTheme['selection-color']", + "selectionOutlineCasingColor": "IrisGridTheme['selection-outline-casing-color']", + "selectionOutlineColor": "IrisGridTheme['selection-outline-color']", + "sortHeaderBarHeight": 2, + "textColor": "IrisGridTheme['text-color']", + "treeLineColor": "IrisGridTheme['tree-line-color']", + "treeMarkerColor": "IrisGridTheme['tree-marker-color']", + "treeMarkerHoverColor": "IrisGridTheme['tree-marker-hover-color']", + "white": "IrisGridTheme['white']", + "zeroLineColor": "IrisGridTheme['zero-line-color']", + "zeroNumberColor": "IrisGridTheme['zero-number-color']", +} +`; diff --git a/packages/iris-grid/src/index.ts b/packages/iris-grid/src/index.ts index 6754afbc16..0d5efc174a 100644 --- a/packages/iris-grid/src/index.ts +++ b/packages/iris-grid/src/index.ts @@ -16,7 +16,7 @@ export { default as IrisGridTableModelTemplate } from './IrisGridTableModelTempl export * from './IrisGridTableModelTemplate'; export * from './IrisGridTreeTableModel'; export { default as IrisGridModelFactory } from './IrisGridModelFactory'; -export { default as IrisGridTheme } from './IrisGridTheme'; +export { createDefaultIrisGridTheme } from './IrisGridTheme'; export type { IrisGridThemeType } from './IrisGridTheme'; export { default as IrisGridTestUtils } from './IrisGridTestUtils'; export { default as IrisGridUtils } from './IrisGridUtils'; diff --git a/packages/jsapi-bootstrap/CHANGELOG.md b/packages/jsapi-bootstrap/CHANGELOG.md index f74a6a7441..9cb9909d1b 100644 --- a/packages/jsapi-bootstrap/CHANGELOG.md +++ b/packages/jsapi-bootstrap/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Features + +* Theme Plugin Loading ([#1524](https://github.com/deephaven/web-client-ui/issues/1524)) ([a9541b1](https://github.com/deephaven/web-client-ui/commit/a9541b108f1d998bb2713e70642f5a54aaf8bd97)), closes [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1530](https://github.com/deephaven/web-client-ui/issues/1530) + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) **Note:** Version bump only for package @deephaven/jsapi-bootstrap diff --git a/packages/jsapi-bootstrap/package.json b/packages/jsapi-bootstrap/package.json index 618a429053..624a9c5ab1 100644 --- a/packages/jsapi-bootstrap/package.json +++ b/packages/jsapi-bootstrap/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/jsapi-bootstrap", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven JSAPI Bootstrap", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/jsapi-components/CHANGELOG.md b/packages/jsapi-components/CHANGELOG.md index 196afb7c78..ce824d19ad 100644 --- a/packages/jsapi-components/CHANGELOG.md +++ b/packages/jsapi-components/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/jsapi-components + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) **Note:** Version bump only for package @deephaven/jsapi-components diff --git a/packages/jsapi-components/package.json b/packages/jsapi-components/package.json index 3f9bcaa612..262e3548e3 100644 --- a/packages/jsapi-components/package.json +++ b/packages/jsapi-components/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/jsapi-components", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven JSAPI Components", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/jsapi-shim/CHANGELOG.md b/packages/jsapi-shim/CHANGELOG.md index b526e8a0d2..6d0d082ede 100644 --- a/packages/jsapi-shim/CHANGELOG.md +++ b/packages/jsapi-shim/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/jsapi-shim + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/jsapi-shim diff --git a/packages/jsapi-shim/package.json b/packages/jsapi-shim/package.json index 63d00992b6..94528927b0 100644 --- a/packages/jsapi-shim/package.json +++ b/packages/jsapi-shim/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/jsapi-shim", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven JSAPI Shim", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/jsapi-types/CHANGELOG.md b/packages/jsapi-types/CHANGELOG.md index d1b585a231..d8bcad4c08 100644 --- a/packages/jsapi-types/CHANGELOG.md +++ b/packages/jsapi-types/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Features + +* data bar render from API ([#1415](https://github.com/deephaven/web-client-ui/issues/1415)) ([ee7d1c1](https://github.com/deephaven/web-client-ui/commit/ee7d1c108e86973b4c6855e482dce21d665dfe28)), closes [#0000](https://github.com/deephaven/web-client-ui/issues/0000) [#FF0000](https://github.com/deephaven/web-client-ui/issues/FF0000) [#FFFF00](https://github.com/deephaven/web-client-ui/issues/FFFF00) [#FFFF00](https://github.com/deephaven/web-client-ui/issues/FFFF00) [#00FF00](https://github.com/deephaven/web-client-ui/issues/00FF00) + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/jsapi-types diff --git a/packages/jsapi-types/package.json b/packages/jsapi-types/package.json index 6e4d690981..debddbc5ae 100644 --- a/packages/jsapi-types/package.json +++ b/packages/jsapi-types/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/jsapi-types", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven JSAPI Types", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/jsapi-types/src/dh.types.ts b/packages/jsapi-types/src/dh.types.ts index 365af150b7..2985b4ca30 100644 --- a/packages/jsapi-types/src/dh.types.ts +++ b/packages/jsapi-types/src/dh.types.ts @@ -35,6 +35,7 @@ export interface dh { FileContents: FileContentsStatic; }; ValueType: typeof ValueType; + Widget: Widget; } const VariableType = { @@ -82,6 +83,20 @@ export interface VariableDefinition { id?: string; } +export interface JsWidget extends Evented { + getDataAsBase64: () => string; + getDataAsU8: () => Uint8Array; + getDataAsString: () => string; + exportedObjects: { + fetch: () => Promise; + }[]; + sendMessage: ( + message: string | ArrayBuffer | ArrayBufferView, + references?: unknown[] + ) => void; + close: () => void; +} + export interface LogItem { micros: number; logLevel: string; @@ -335,6 +350,26 @@ export interface Figure extends Evented { close(): void; } +export type WidgetExportedObject = { + type: string; + fetch: () => Promise; + close: () => void; +}; + +export interface Widget { + readonly EVENT_MESSAGE: string; + + addEventListener: ( + type: string, + listener: (event: unknown) => void + ) => () => void; + getDataAsBase64(): string; + getDataAsString(): string; + getDataAsU8(): Uint8Array; + sendMessage: (message: string, references?: never[]) => void; + exportedObjects: WidgetExportedObject[]; +} + export interface FigureDataUpdatedEvent { /** * The series instances which were affected by this event and need to be updated. diff --git a/packages/jsapi-utils/CHANGELOG.md b/packages/jsapi-utils/CHANGELOG.md index c346d60cae..5ea079b73e 100644 --- a/packages/jsapi-utils/CHANGELOG.md +++ b/packages/jsapi-utils/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/jsapi-utils + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/jsapi-utils diff --git a/packages/jsapi-utils/package.json b/packages/jsapi-utils/package.json index 00a4016509..4ecc0eb80d 100644 --- a/packages/jsapi-utils/package.json +++ b/packages/jsapi-utils/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/jsapi-utils", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven JSAPI Utils", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/log/CHANGELOG.md b/packages/log/CHANGELOG.md index b9dc117be7..b460c0762a 100644 --- a/packages/log/CHANGELOG.md +++ b/packages/log/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/log + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/log diff --git a/packages/log/package.json b/packages/log/package.json index acae3fe9a3..5503fedb38 100644 --- a/packages/log/package.json +++ b/packages/log/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/log", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven Logger", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/mocks/CHANGELOG.md b/packages/mocks/CHANGELOG.md index 6de1ba9e78..67ae452342 100644 --- a/packages/mocks/CHANGELOG.md +++ b/packages/mocks/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/mocks + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/mocks diff --git a/packages/mocks/package.json b/packages/mocks/package.json index 619a8b026e..9a5864d515 100644 --- a/packages/mocks/package.json +++ b/packages/mocks/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/mocks", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven Mocks for common libraries", "repository": { "type": "git", diff --git a/packages/plugin/CHANGELOG.md b/packages/plugin/CHANGELOG.md index 67bbfb2797..d01b10d338 100644 --- a/packages/plugin/CHANGELOG.md +++ b/packages/plugin/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +### Features + +* Theme Plugin Loading ([#1524](https://github.com/deephaven/web-client-ui/issues/1524)) ([a9541b1](https://github.com/deephaven/web-client-ui/commit/a9541b108f1d998bb2713e70642f5a54aaf8bd97)), closes [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1530](https://github.com/deephaven/web-client-ui/issues/1530) + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) **Note:** Version bump only for package @deephaven/plugin diff --git a/packages/plugin/package.json b/packages/plugin/package.json index dd05353d1b..798e1aade7 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/plugin", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven JS Plugin Core", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", @@ -23,8 +23,15 @@ }, "dependencies": { "@deephaven/components": "file:../components", + "@deephaven/golden-layout": "file:../golden-layout", + "@deephaven/icons": "file:../icons", "@deephaven/iris-grid": "file:../iris-grid", - "@deephaven/jsapi-types": "file:../jsapi-types" + "@deephaven/jsapi-types": "file:../jsapi-types", + "@fortawesome/fontawesome-common-types": "^6.1.1", + "@fortawesome/react-fontawesome": "^0.2.0" + }, + "peerDependencies": { + "react": "^17.x" }, "files": [ "dist" diff --git a/packages/plugin/src/PluginTypes.ts b/packages/plugin/src/PluginTypes.ts index 86b513dff7..7a72ebd21e 100644 --- a/packages/plugin/src/PluginTypes.ts +++ b/packages/plugin/src/PluginTypes.ts @@ -1,9 +1,16 @@ import type { BaseThemeType } from '@deephaven/components'; +import { type JsWidget } from '@deephaven/jsapi-types'; +import { + type EventEmitter, + type ItemContainer, +} from '@deephaven/golden-layout'; +import type { IconDefinition } from '@fortawesome/fontawesome-common-types'; import type { TablePluginComponent } from './TablePlugin'; export const PluginType = Object.freeze({ AUTH_PLUGIN: 'AuthPlugin', DASHBOARD_PLUGIN: 'DashboardPlugin', + WIDGET_PLUGIN: 'WidgetPlugin', TABLE_PLUGIN: 'TablePlugin', THEME_PLUGIN: 'ThemePlugin', }); @@ -67,7 +74,14 @@ export function isLegacyPlugin(plugin: unknown): plugin is LegacyPlugin { export type PluginModule = Plugin | LegacyPlugin; export interface Plugin { + /** + * The name of the plugin. This will be used as an identifier for the plugin and should be unique. + */ name: string; + + /** + * The type of plugin. + */ type: (typeof PluginType)[keyof typeof PluginType]; } @@ -76,6 +90,10 @@ export interface Plugin { */ export interface DashboardPlugin extends Plugin { type: typeof PluginType.DASHBOARD_PLUGIN; + /** + * The component to mount for the dashboard plugin. + * This component is used to initialize the plugin and will only be mounted to the dashboard once. + */ // eslint-disable-next-line @typescript-eslint/no-explicit-any component: React.ComponentType; } @@ -86,6 +104,67 @@ export function isDashboardPlugin( return 'type' in plugin && plugin.type === PluginType.DASHBOARD_PLUGIN; } +export interface WidgetComponentProps { + fetch: () => Promise; + metadata?: { + id?: string; + name?: string; + type?: string; + }; + localDashboardId: string; + glContainer: ItemContainer; + glEventHub: EventEmitter; +} + +export interface WidgetPlugin extends Plugin { + type: typeof PluginType.WIDGET_PLUGIN; + /** + * The component that can render the widget types the plugin supports. + * + * If the widget should be opened as a panel by itself (determined by the UI), + * then `panelComponent` will be used instead. + * The component will be wrapped in a default panel if `panelComponent` is not provided. + */ + component: React.ComponentType; + + /** + * The server widget types that this plugin will handle. + */ + supportedTypes: string | string[]; + + /** + * The title to display for widgets handled by the plugin. + * This is a user friendly name to denote the type of widget. + * Does not have to be unique across plugins. + * If not specified, the plugin name will be used as the title. + * + * A plugin may have a name of `@deehaven/pandas` and a title of `Pandas`. + * This way, the user will just see `Pandas panel` instead of `@deephaven/pandas panel`. + */ + title?: string; + + /** + * The component to use if the widget should be mounted as a panel. + * If omitted, the default panel will be used. + * This provides access to panel events such as onHide and onTabFocus. + * + * See @deephaven/dashboard-core-plugins WidgetPanel for the component that should be used here. + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any + panelComponent?: React.ComponentType; + + /** + * The icon to display next to the console button. + * If a react node is provided (including a string), it will be rendered directly. + * If no icon is specified, the default widget icon will be used. + */ + icon?: IconDefinition | React.ReactElement; +} + +export function isWidgetPlugin(plugin: PluginModule): plugin is WidgetPlugin { + return 'type' in plugin && plugin.type === PluginType.WIDGET_PLUGIN; +} + export interface TablePlugin extends Plugin { type: typeof PluginType.TABLE_PLUGIN; component: TablePluginComponent; diff --git a/packages/plugin/src/PluginUtils.test.tsx b/packages/plugin/src/PluginUtils.test.tsx new file mode 100644 index 0000000000..27bbac972e --- /dev/null +++ b/packages/plugin/src/PluginUtils.test.tsx @@ -0,0 +1,60 @@ +import React from 'react'; +import { dhTruck, vsPreview } from '@deephaven/icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { DashboardPlugin, PluginType, type WidgetPlugin } from './PluginTypes'; +import { pluginSupportsType, getIconForPlugin } from './PluginUtils'; + +function TestWidget() { + return
TestWidget
; +} + +const widgetPlugin: WidgetPlugin = { + name: 'test-widget-plugin', + type: PluginType.WIDGET_PLUGIN, + component: TestWidget, + supportedTypes: ['test-widget', 'test-widget-two'], +}; + +const dashboardPlugin: DashboardPlugin = { + name: 'test-widget-plugin', + type: PluginType.DASHBOARD_PLUGIN, + component: TestWidget, +}; + +test('pluginSupportsType', () => { + expect(pluginSupportsType(widgetPlugin, 'test-widget')).toBe(true); + expect(pluginSupportsType(widgetPlugin, 'test-widget-two')).toBe(true); + expect(pluginSupportsType(widgetPlugin, 'test-widget-three')).toBe(false); + expect(pluginSupportsType(dashboardPlugin, 'test-widget')).toBe(false); + expect(pluginSupportsType(undefined, 'test-widget')).toBe(false); +}); + +const DEFAULT_ICON = ; + +describe('getIconForPlugin', () => { + test('default icon', () => { + expect(getIconForPlugin(widgetPlugin)).toEqual(DEFAULT_ICON); + }); + + test('default icon for non-widget plugin', () => { + expect(getIconForPlugin(dashboardPlugin)).toEqual(DEFAULT_ICON); + }); + + test('custom icon', () => { + const customIcon = ; + const customWidgetPlugin: WidgetPlugin = { + ...widgetPlugin, + icon: dhTruck, + }; + expect(getIconForPlugin(customWidgetPlugin)).toEqual(customIcon); + }); + + test('custom icon element', () => { + const customIcon =
Test
; + const customWidgetPlugin: WidgetPlugin = { + ...widgetPlugin, + icon: customIcon, + }; + expect(getIconForPlugin(customWidgetPlugin)).toEqual(customIcon); + }); +}); diff --git a/packages/plugin/src/PluginUtils.tsx b/packages/plugin/src/PluginUtils.tsx new file mode 100644 index 0000000000..6fa9024153 --- /dev/null +++ b/packages/plugin/src/PluginUtils.tsx @@ -0,0 +1,34 @@ +import { isValidElement } from 'react'; +import { vsPreview } from '@deephaven/icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { type PluginModule, isWidgetPlugin } from './PluginTypes'; + +export function pluginSupportsType( + plugin: PluginModule | undefined, + type: string +): boolean { + if (plugin == null || !isWidgetPlugin(plugin)) { + return false; + } + + return [plugin.supportedTypes].flat().some(t => t === type); +} + +export function getIconForPlugin(plugin: PluginModule): React.ReactElement { + const defaultIcon = ; + if (!isWidgetPlugin(plugin)) { + return defaultIcon; + } + + const { icon } = plugin; + + if (icon == null) { + return defaultIcon; + } + + if (isValidElement(icon)) { + return icon; + } + + return ; +} diff --git a/packages/plugin/src/index.ts b/packages/plugin/src/index.ts index 4e055db1fe..6685a9de1d 100644 --- a/packages/plugin/src/index.ts +++ b/packages/plugin/src/index.ts @@ -1,2 +1,3 @@ export * from './PluginTypes'; export * from './TablePlugin'; +export * from './PluginUtils'; diff --git a/packages/plugin/tsconfig.json b/packages/plugin/tsconfig.json index 1e7fecd870..45ec8489bc 100644 --- a/packages/plugin/tsconfig.json +++ b/packages/plugin/tsconfig.json @@ -8,6 +8,7 @@ "exclude": ["node_modules", "src/**/*.test.*", "src/**/__mocks__/*"], "references": [ { "path": "../components" }, + { "path": "../golden-layout" }, { "path": "../iris-grid" }, { "path": "../jsapi-types" } ] diff --git a/packages/pouch-storage/CHANGELOG.md b/packages/pouch-storage/CHANGELOG.md index 17e6ae3799..d65b0e1bd3 100644 --- a/packages/pouch-storage/CHANGELOG.md +++ b/packages/pouch-storage/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/pouch-storage + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) **Note:** Version bump only for package @deephaven/pouch-storage diff --git a/packages/pouch-storage/package.json b/packages/pouch-storage/package.json index dd72f6ecf7..969b5fcf13 100644 --- a/packages/pouch-storage/package.json +++ b/packages/pouch-storage/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/pouch-storage", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven Storage based on PouchDB", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/prettier-config/CHANGELOG.md b/packages/prettier-config/CHANGELOG.md index ee9799db11..abd49ca37c 100644 --- a/packages/prettier-config/CHANGELOG.md +++ b/packages/prettier-config/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/prettier-config + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/prettier-config diff --git a/packages/prettier-config/package.json b/packages/prettier-config/package.json index f3270af880..368e68d3cc 100644 --- a/packages/prettier-config/package.json +++ b/packages/prettier-config/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/prettier-config", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven Prettier configuration", "repository": { "type": "git", diff --git a/packages/react-hooks/CHANGELOG.md b/packages/react-hooks/CHANGELOG.md index 7f70d2f76b..a4044dd8eb 100644 --- a/packages/react-hooks/CHANGELOG.md +++ b/packages/react-hooks/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/react-hooks + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/react-hooks diff --git a/packages/react-hooks/package.json b/packages/react-hooks/package.json index 348194e01f..1163d5d60f 100644 --- a/packages/react-hooks/package.json +++ b/packages/react-hooks/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/react-hooks", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven React hooks library", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/redux/CHANGELOG.md b/packages/redux/CHANGELOG.md index c383eada4e..7fc9f174a6 100644 --- a/packages/redux/CHANGELOG.md +++ b/packages/redux/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/redux + + + + + ## [0.49.1](https://github.com/deephaven/web-client-ui/compare/v0.49.0...v0.49.1) (2023-09-27) **Note:** Version bump only for package @deephaven/redux diff --git a/packages/redux/package.json b/packages/redux/package.json index 260fe417ba..eeaf158f9d 100644 --- a/packages/redux/package.json +++ b/packages/redux/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/redux", - "version": "0.49.1", + "version": "0.50.0", "description": "Deephaven Redux", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/redux/src/selectors.ts b/packages/redux/src/selectors.ts index 1b784f5b2c..dfbbad7ae6 100644 --- a/packages/redux/src/selectors.ts +++ b/packages/redux/src/selectors.ts @@ -111,6 +111,11 @@ export const getActiveTool = ( store: State ): State['activeTool'] => store.activeTool; +/** + * @deprecated Use `usePlugins` hook instead or `PluginsContext` directly + * @param store Redux store + * @returns Plugins map + */ export const getPlugins = ( store: State ): State['plugins'] => store.plugins ?? EMPTY_MAP; diff --git a/packages/storage/CHANGELOG.md b/packages/storage/CHANGELOG.md index d00c8f9d5a..a5168966a9 100644 --- a/packages/storage/CHANGELOG.md +++ b/packages/storage/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/storage + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/storage diff --git a/packages/storage/package.json b/packages/storage/package.json index f77bb79c63..63591fcc70 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/storage", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven Storage abstract classes for storing app data", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/stylelint-config/CHANGELOG.md b/packages/stylelint-config/CHANGELOG.md index 4fef0542d5..4495da75ec 100644 --- a/packages/stylelint-config/CHANGELOG.md +++ b/packages/stylelint-config/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/stylelint-config + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/stylelint-config diff --git a/packages/stylelint-config/package.json b/packages/stylelint-config/package.json index f07407a348..6bf6b23282 100644 --- a/packages/stylelint-config/package.json +++ b/packages/stylelint-config/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/stylelint-config", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven Stylelint configuration", "repository": { "type": "git", diff --git a/packages/tsconfig/CHANGELOG.md b/packages/tsconfig/CHANGELOG.md index fdfa398236..e672075e1e 100644 --- a/packages/tsconfig/CHANGELOG.md +++ b/packages/tsconfig/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + +**Note:** Version bump only for package @deephaven/tsconfig + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/tsconfig diff --git a/packages/tsconfig/package.json b/packages/tsconfig/package.json index f6b370d958..b98503ef81 100644 --- a/packages/tsconfig/package.json +++ b/packages/tsconfig/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/tsconfig", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven TypeScript configuration", "repository": { "type": "git", diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index 44a27dd144..b7490ffd9b 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -3,6 +3,30 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [0.50.0](https://github.com/deephaven/web-client-ui/compare/v0.49.1...v0.50.0) (2023-10-13) + + +* fix!: CSS based loading spinner (#1532) ([f06fbb0](https://github.com/deephaven/web-client-ui/commit/f06fbb01e27eaaeccab6031d8ff010ffee303d99)), closes [#1532](https://github.com/deephaven/web-client-ui/issues/1532) [#1531](https://github.com/deephaven/web-client-ui/issues/1531) + + +### Features + +* Monaco theming ([#1560](https://github.com/deephaven/web-client-ui/issues/1560)) ([4eda17c](https://github.com/deephaven/web-client-ui/commit/4eda17c82f6c177a11ba600d6f43c4f36915f6bd)), closes [#1542](https://github.com/deephaven/web-client-ui/issues/1542) +* Theme Plugin Loading ([#1524](https://github.com/deephaven/web-client-ui/issues/1524)) ([a9541b1](https://github.com/deephaven/web-client-ui/commit/a9541b108f1d998bb2713e70642f5a54aaf8bd97)), closes [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1a171](https://github.com/deephaven/web-client-ui/issues/1a171) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#4c7](https://github.com/deephaven/web-client-ui/issues/4c7) [#1530](https://github.com/deephaven/web-client-ui/issues/1530) + + +### BREAKING CHANGES + +* Theme variables have to be present on body to avoid +Monaco init failing +* Inline LoadingSpinner instances will need to be +decorated with `className="loading-spinner-vertical-align"` for vertical +alignment to work as before + + + + + # [0.49.0](https://github.com/deephaven/web-client-ui/compare/v0.48.0...v0.49.0) (2023-09-15) **Note:** Version bump only for package @deephaven/utils diff --git a/packages/utils/package.json b/packages/utils/package.json index 69e8527c15..240da1e6b8 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@deephaven/utils", - "version": "0.49.0", + "version": "0.50.0", "description": "Deephaven Utils", "author": "Deephaven Data Labs LLC", "license": "Apache-2.0", diff --git a/packages/utils/src/ColorUtils.ts b/packages/utils/src/ColorUtils.ts index 560b9fd6aa..297994df44 100644 --- a/packages/utils/src/ColorUtils.ts +++ b/packages/utils/src/ColorUtils.ts @@ -100,12 +100,7 @@ class ColorUtils { const [r, g, b, a = 1] = tokens.map(Number); - return { - r, - g, - b, - a, - }; + return { r, g, b, a }; } /** diff --git a/playwright.config.ts b/playwright.config.ts index 280b040043..cd6c7c6615 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -65,6 +65,30 @@ const config: PlaywrightTestConfig = { name: 'firefox', use: { ...devices['Desktop Firefox'], + // https://playwright.dev/docs/test-use-options#more-browser-and-context-options + launchOptions: { + // https://playwright.dev/docs/api/class-browsertype#browser-type-launch-option-firefox-user-prefs + firefoxUserPrefs: { + // By default, headless Firefox runs as though no pointers capabilities + // are available. + // https://github.com/microsoft/playwright/issues/7769#issuecomment-966098074 + // + // This impacts React Spectrum which uses an '(any-pointer: fine)' + // media query to determine font size. It also causes certain chart + // elements to always be visible that should only be visible on + // hover. + // + // Available values for pointer capabilities: + // NO_POINTER = 0x00; + // COARSE_POINTER = 0x01; + // FINE_POINTER = 0x02; + // HOVER_CAPABLE_POINTER = 0x04; + // + // Setting to 0x02 | 0x04 says the system supports a mouse + 'ui.primaryPointerCapabilities': 0x02 | 0x04, + 'ui.allPointerCapabilities': 0x02 | 0x04, + }, + }, }, }, diff --git a/tests/figure.spec.ts-snapshots/can-open-a-simple-figure-1-firefox-linux.png b/tests/figure.spec.ts-snapshots/can-open-a-simple-figure-1-firefox-linux.png index 2faf025b43..13f98dd478 100644 Binary files a/tests/figure.spec.ts-snapshots/can-open-a-simple-figure-1-firefox-linux.png and b/tests/figure.spec.ts-snapshots/can-open-a-simple-figure-1-firefox-linux.png differ diff --git a/tests/figure.spec.ts-snapshots/can-set-point-shape-and-size-1-firefox-linux.png b/tests/figure.spec.ts-snapshots/can-set-point-shape-and-size-1-firefox-linux.png index 9d101fbbfb..1cdb88ffc0 100644 Binary files a/tests/figure.spec.ts-snapshots/can-set-point-shape-and-size-1-firefox-linux.png and b/tests/figure.spec.ts-snapshots/can-set-point-shape-and-size-1-firefox-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-1-chromium-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-1-chromium-linux.png index 66e8100836..b780e4cbbb 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-1-chromium-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-1-chromium-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-1-firefox-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-1-firefox-linux.png index e7f2ffbfba..23bd07d68b 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-1-firefox-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-1-firefox-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-1-webkit-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-1-webkit-linux.png index b47300ecbc..8446e49fd5 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-1-webkit-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-1-webkit-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-2-chromium-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-2-chromium-linux.png index d4801a4724..08ccdd76d3 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-2-chromium-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-2-chromium-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-2-firefox-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-2-firefox-linux.png index 03cdbb8684..a0880f72d3 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-2-firefox-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-2-firefox-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-2-webkit-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-2-webkit-linux.png index 8bd046af9d..47370be3ba 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-2-webkit-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-2-webkit-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-3-chromium-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-3-chromium-linux.png index 4c1987805d..72161db66f 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-3-chromium-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-3-chromium-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-3-firefox-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-3-firefox-linux.png index f65a50fa1c..ff7ea1c4b1 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-3-firefox-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-3-firefox-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-3-webkit-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-3-webkit-linux.png index 21e214d568..1717ae9bdc 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-3-webkit-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-3-webkit-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-4-chromium-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-4-chromium-linux.png index 2636ae6d84..c46011cf3c 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-4-chromium-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-4-chromium-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-4-firefox-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-4-firefox-linux.png index d421320741..3e57774343 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-4-firefox-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-4-firefox-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-4-webkit-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-4-webkit-linux.png index db02aeb0a7..39a8098eee 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-4-webkit-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-4-webkit-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-5-chromium-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-5-chromium-linux.png index 67d89ae466..1ea62c210f 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-5-chromium-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-5-chromium-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-5-firefox-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-5-firefox-linux.png index 140922d569..832efd0b29 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-5-firefox-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-5-firefox-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-5-webkit-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-5-webkit-linux.png index 266959ec4e..099ae4b89d 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-5-webkit-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-5-webkit-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-6-chromium-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-6-chromium-linux.png index 55131ce706..09b7dbfc69 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-6-chromium-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-6-chromium-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-6-firefox-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-6-firefox-linux.png index e7a7a2fd0a..0d118afe91 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-6-firefox-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-6-firefox-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-6-webkit-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-6-webkit-linux.png index 14b382209e..96263e72ec 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-6-webkit-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-6-webkit-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-7-chromium-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-7-chromium-linux.png index 8e315668d9..f384881e5d 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-7-chromium-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-7-chromium-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-7-firefox-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-7-firefox-linux.png index 8b7bad8d14..b7686d07b0 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-7-firefox-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-7-firefox-linux.png differ diff --git a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-7-webkit-linux.png b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-7-webkit-linux.png index 0883271226..03917650b2 100644 Binary files a/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-7-webkit-linux.png and b/tests/table-operations.spec.ts-snapshots/rollup-rows-and-aggregrate-columns-7-webkit-linux.png differ diff --git a/tests/table.spec.ts-snapshots/tests-simple-table-operations-go-to-1-chromium-linux.png b/tests/table.spec.ts-snapshots/tests-simple-table-operations-go-to-1-chromium-linux.png index 4697fe11db..067bf33c35 100644 Binary files a/tests/table.spec.ts-snapshots/tests-simple-table-operations-go-to-1-chromium-linux.png and b/tests/table.spec.ts-snapshots/tests-simple-table-operations-go-to-1-chromium-linux.png differ diff --git a/tests/table.spec.ts-snapshots/tests-simple-table-operations-go-to-1-firefox-linux.png b/tests/table.spec.ts-snapshots/tests-simple-table-operations-go-to-1-firefox-linux.png index f105166d15..3da537b491 100644 Binary files a/tests/table.spec.ts-snapshots/tests-simple-table-operations-go-to-1-firefox-linux.png and b/tests/table.spec.ts-snapshots/tests-simple-table-operations-go-to-1-firefox-linux.png differ diff --git a/tests/table.spec.ts-snapshots/tests-simple-table-operations-go-to-1-webkit-linux.png b/tests/table.spec.ts-snapshots/tests-simple-table-operations-go-to-1-webkit-linux.png index 70ef232433..288bb1d605 100644 Binary files a/tests/table.spec.ts-snapshots/tests-simple-table-operations-go-to-1-webkit-linux.png and b/tests/table.spec.ts-snapshots/tests-simple-table-operations-go-to-1-webkit-linux.png differ