diff --git a/CHANGELOG.md b/CHANGELOG.md index 5182705..5af7239 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## v0.7.0 + +- Upgrade to Material 3 Web Components (https://material-web.dev/). +- Use Web Test Runner instead of Karma. + ## v0.6.6 - Add a scrollbar to the right panel of the Matches tab. diff --git a/README.md b/README.md index 4085d28..6376613 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,9 @@ page can understand what is shown, but also useful to experts, by offering a convenient interactive user interface with matcher, metric and filter settings. The presented data should be easily reproducible and up-to-date. -In contrast to more traditional +Codec-Compare is based on +[Rate-Complexity Clouds](https://doi.org/10.1109/PCS65673.2025.11417613) rather +than Rate-Distortion Curves. In contrast to more traditional [comparative benchmarks](https://storage.googleapis.com/avif-comparison/index.html), Codec-Compare aims to aggregate statistics after comparing pairs of two similarly encoded images, to avoid some of the bias brought by comparing already @@ -82,7 +84,7 @@ Codec-Compare has: `npm run build`). - A `vite.config.js` Vite configuration file (used by `npm run dev` and `npm run build`). - - A `karma.conf.js` Karma configuration file (used by `npm run test`). + - A `web-test-runner.config.mjs` configuration file (used by `npm run test`). Note: See https://lit.dev/docs/components/properties/#avoiding-issues-with-class-fields diff --git a/index.html b/index.html index fa13fd4..74fa120 100644 --- a/index.html +++ b/index.html @@ -20,19 +20,21 @@ Codec Compare + + - diff --git a/karma.conf.js b/karma.conf.js deleted file mode 100644 index 75cb5bd..0000000 --- a/karma.conf.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @license - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * See http://karma-runner.github.io/6.4/config/files.html#loading-assets. - * @param {!Object} config - */ -module.exports = (config) => { - config.set({ - frameworks: ['jasmine', 'karma-typescript'], - plugins: [ - 'karma-jasmine', 'karma-chrome-launcher', 'karma-typescript', - 'karma-spec-reporter' - ], - karmaTypescriptConfig: { - tsconfig: './tsconfig.json', - bundlerOptions: - {transforms: [require('karma-typescript-es6-transform')()]} - }, - files: [ - {pattern: 'src/**/*.ts'}, - {pattern: 'assets/**', watched: false, included: false, served: true} - ], - proxies: {'/assets/': '/base/assets/'}, - preprocessors: {'src/**/*.ts': ['karma-typescript']}, - reporters: ['spec', 'karma-typescript'], - colors: true, - logLevel: config.LOG_INFO, - browsers: ['ChromeHeadless'], - // Makes "karma start" return. Avoids the need for Ctrl+C after "npm test". - singleRun: true - }); -}; \ No newline at end of file diff --git a/package.json b/package.json index 91c1ec4..e06f060 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "codec_compare", - "version": "0.6.6", + "version": "0.7.0", "description": "Codec performance comparison tool", "publisher": "Google LLC", "author": "Yannis Guyon", @@ -10,37 +10,22 @@ "build": "vite build", "postbuild": "./postbuild.sh", "preview": "vite preview --open", - "test": "karma start" + "test": "web-test-runner \"src/**/*_test.ts\" --node-resolve" }, "devDependencies": { - "@types/jasmine": "^5.1.4", - "@types/node": "^20.10.4", + "@types/jasmine": "^5.1.5", + "@types/node": "^22.10.2", "@types/plotly.js-dist": "npm:@types/plotly.js@^2.12.30", - "jasmine-core": "^5.1.1", - "karma": "^6.4.2", - "karma-chrome-launcher": "^3.2.0", - "karma-jasmine": "^5.1.0", - "karma-spec-reporter": "^0.0.36", - "karma-typescript": "^5.5.4", - "karma-typescript-es6-transform": "^5.5.4", - "typescript": "^5.3.3", - "vite": "^6.3.2" + "@web/dev-server-esbuild": "^1.0.4", + "@web/test-runner": "^0.19.0", + "jasmine-core": "^5.5.0", + "typescript": "^5.7.2", + "vite": "^6.3.2", + "web-test-runner-jasmine": "^0.0.6" }, "dependencies": { - "@material/mwc-button": "^0.27.0", - "@material/mwc-checkbox": "^0.27.0", - "@material/mwc-fab": "^0.27.0", - "@material/mwc-icon": "^0.27.0", - "@material/mwc-icon-button": "^0.27.0", - "@material/mwc-linear-progress": "^0.27.0", - "@material/mwc-menu": "^0.27.0", - "@material/mwc-slider": "^0.27.0", - "@material/mwc-snackbar": "^0.27.0", - "@material/mwc-switch": "^0.27.0", - "@material/mwc-tab": "^0.27.0", - "@material/mwc-tab-bar": "^0.27.0", - "@material/mwc-textfield": "^0.27.0", - "lit": "^3.1.0", - "plotly.js-dist": "^2.27.1" + "@material/web": "^1.4.1", + "lit": "^3.2.1", + "plotly.js-dist": "^2.35.3" } } diff --git a/readme_preview.png b/readme_preview.png index 5c5d806..b5b19e2 100644 Binary files a/readme_preview.png and b/readme_preview.png differ diff --git a/src/batch_name_ui.ts b/src/batch_name_ui.ts index f29e0b0..e9f7251 100644 --- a/src/batch_name_ui.ts +++ b/src/batch_name_ui.ts @@ -42,7 +42,7 @@ export class BatchNameUi extends LitElement { vertical-align: middle; } .mono { - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); font-family: monospace; vertical-align: middle; } diff --git a/src/batch_selection_actions_ui.ts b/src/batch_selection_actions_ui.ts index 6746711..8fe7e84 100644 --- a/src/batch_selection_actions_ui.ts +++ b/src/batch_selection_actions_ui.ts @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-icon-button'; +import '@material/web/iconbutton/icon-button'; +import '@material/web/icon/icon'; import {css, html, LitElement} from 'lit'; import {customElement, property} from 'lit/decorators.js'; @@ -36,26 +37,27 @@ export class BatchSelectionActionsUi extends LitElement { const batchSelection = this.state.batchSelections[this.batchSelectionIndex]; return html` - { batchSelection.isDisplayed = !batchSelection.isDisplayed; dispatch(EventType.MATCHED_DATA_POINTS_CHANGED); this.requestUpdate(); }}> - + ${ + batchSelection.isDisplayed ? 'visibility' : 'visibility_off'} + `; } static override styles = css` - mwc-icon-button { - color: var(--mdc-theme-text); - /* Make the background disk that appears when hovered slightly bigger - * than the icon itself, which is 24px. */ - --mdc-icon-button-size: 28px; - /* Tighten the buttons to save space. */ - margin: -2px; + md-icon-button { + color: var(--md-sys-color-text); + --md-icon-button-icon-size: 20px; + --md-icon-button-state-layer-width: 24px; + --md-icon-button-state-layer-height: 24px; + /* The touch area is hardcoded as at least 48px by 48px. */ + overflow: hidden; } `; } diff --git a/src/batch_selection_test.ts b/src/batch_selection_test.ts index 41818dc..ecafcb1 100644 --- a/src/batch_selection_test.ts +++ b/src/batch_selection_test.ts @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'jasmine'; - import {BatchSelection} from './batch_selection'; import {Batch, Field} from './entry'; import {dispatch, EventType} from './events'; diff --git a/src/batch_selection_ui.ts b/src/batch_selection_ui.ts index 5d9bb54..2ac21dc 100644 --- a/src/batch_selection_ui.ts +++ b/src/batch_selection_ui.ts @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-button'; import './filtered_images_ui'; import './filters_ui'; diff --git a/src/batch_selections_ui.ts b/src/batch_selections_ui.ts index 1467cde..308ec06 100644 --- a/src/batch_selections_ui.ts +++ b/src/batch_selections_ui.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-icon'; +import '@material/web/icon/icon'; import './batch_selection_actions_ui'; import {css, html, LitElement} from 'lit'; @@ -111,7 +111,7 @@ export class BatchSelectionsUi extends LitElement { EventType.FILTERED_DATA_INFO_REQUEST, {batchIndex: batchSelection.batch.index}); }}> - filter_alt + filter_alt ${field.displayName}=${this.filterChipText(field, fieldFilter)} `; } @@ -187,14 +187,14 @@ export class BatchSelectionsUi extends LitElement { static override styles = css` :host { box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 6px 0px; - /* Necessary for mwc-menus to work properly without hacks. */ + /* Necessary for md-menus to work properly without hacks. */ overflow: visible; /* Does not work without overflow: hidden; */ border-radius: 5px; } table { - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); width: 100%; white-space: nowrap; border-collapse: collapse; @@ -206,21 +206,21 @@ export class BatchSelectionsUi extends LitElement { border-style: solid; } th { - border-color: var(--mdc-theme-background); - background: var(--mdc-theme-surface); + border-color: var(--md-sys-color-background); + background: var(--md-sys-color-surface); font-size: 20px; } td { - border-color: var(--mdc-theme-surface); + border-color: var(--md-sys-color-surface); font-family: monospace; font-size: 16px; } tr { - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); } tr:hover { - box-shadow: inset 0 0 8px 4px var(--mdc-theme-surface); + box-shadow: inset 0 0 8px 4px var(--md-sys-color-surface); } tr:not(:hover) batch-selection-actions-ui { /* Dim the action buttons when the table row is not hovered. */ @@ -249,12 +249,12 @@ export class BatchSelectionsUi extends LitElement { } #filterChip { - --mdc-icon-size: 12px; + --md-icon-size: 12px; font-size: 10px; padding: 2px 4px; border-radius: 30px; - background: var(--mdc-theme-primary); - color: var(--mdc-theme-background); + background: var(--md-sys-color-primary); + color: var(--md-sys-color-background); display: flex; align-items: center; justify-content: center; @@ -265,8 +265,8 @@ export class BatchSelectionsUi extends LitElement { } .referenceBatchChip { - background: var(--mdc-theme-primary); - color: var(--mdc-theme-background); + background: var(--md-sys-color-primary); + color: var(--md-sys-color-background); border-radius: 16px; padding: 2px 8px; font-size: 12px; diff --git a/src/batch_selections_ui_test.ts b/src/batch_selections_ui_test.ts index b64febb..563c957 100644 --- a/src/batch_selections_ui_test.ts +++ b/src/batch_selections_ui_test.ts @@ -11,8 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - -import 'jasmine'; import './batch_selections_ui'; import {Batch, Field} from './entry'; diff --git a/src/batch_ui.ts b/src/batch_ui.ts index 16e60a6..70fe6f3 100644 --- a/src/batch_ui.ts +++ b/src/batch_ui.ts @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-button'; +import '@material/web/button/filled-button'; +import '@material/web/icon/icon'; import './batch_name_ui'; import './constants_table_ui'; import './fields_table_ui'; @@ -62,49 +63,50 @@ export class BatchUi extends LitElement {
- - + Download batch + download + ${ this.state.batches.length <= 2 ? html`` : batchIndex === refIndex ? - // disabled mwc-button title does not appear. Use a div. + // disabled md-filled-button title does not appear. Use a div. html`
- - open_in_new - + Two-batch view + open_in_new + filter_2 +
` : html` - - open_in_new - + Two-batch view + open_in_new + filter_2 + `} ${rdModeHash === undefined ? html`` : html` - - open_in_new - + Rate-Distortion + open_in_new + stacked_line_chart + `}
`; } @@ -119,7 +121,7 @@ export class BatchUi extends LitElement { } h2 { - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); margin-bottom: 0; } @@ -139,9 +141,13 @@ export class BatchUi extends LitElement { margin-left: auto; } - mwc-icon { + .md-icon-in-md-button { margin-left: 8px; - font-size: 16px; + vertical-align: middle; + --md-icon-size: 20px; + } + .md-button-with-md-icon { + --md-filled-button-with-leading-icon-trailing-space: 16px; } a { diff --git a/src/batch_ui_test.ts b/src/batch_ui_test.ts index c75e8af..edc960d 100644 --- a/src/batch_ui_test.ts +++ b/src/batch_ui_test.ts @@ -11,8 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - -import 'jasmine'; import './batch_ui'; import './constants_table_ui'; import './fields_table_ui'; diff --git a/src/codec_compare.ts b/src/codec_compare.ts index 5940b7d..272b813 100644 --- a/src/codec_compare.ts +++ b/src/codec_compare.ts @@ -12,11 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-button'; -import '@material/mwc-icon'; -import '@material/mwc-menu'; -import '@material/mwc-tab-bar'; -import '@material/mwc-tab'; +import '@material/web/button/filled-button'; +import '@material/web/button/text-button'; +import '@material/web/icon/icon'; +import '@material/web/menu/menu'; +import '@material/web/tabs/tabs'; +import '@material/web/tabs/primary-tab'; import './batch_name_ui'; import './batch_selections_ui'; import './help_ui'; @@ -24,13 +25,12 @@ import './gallery_ui'; import './loading_ui'; import './matchers_ui'; import './metrics_ui'; -import './mwc_button_fit'; import './panel_ui'; import './sentence_ui'; import './settings_ui'; -import {ActionDetail} from '@material/mwc-list'; -import {Menu} from '@material/mwc-menu'; +import {MdMenu} from '@material/web/menu/menu'; +import {MdTabs} from '@material/web/tabs/tabs'; import {css, html, LitElement} from 'lit'; import {customElement, query} from 'lit/decorators.js'; @@ -71,40 +71,41 @@ export class CodecCompare extends LitElement { @query('help-ui') private readonly helpUi!: HelpUi; @query('loading-ui') private readonly loadingUi!: LoadingUi; - @query('#referenceMenu') private readonly referenceMenu!: Menu; + @query('#referenceMenu') private readonly referenceMenu!: MdMenu; private renderReference(referenceBatch: Batch) { // Use a span to avoid breaking the line between the button and the comma. return html` - - + { this.referenceMenu.show(); }}> - , + arrow_drop_down + , - ) => { - this.state.referenceBatchSelectionIndex = e.detail.index; - dispatch(EventType.REFERENCE_CHANGED); - }}> + ${ this.state.batches.map( (batch) => html` - + { + this.state.referenceBatchSelectionIndex = batch.index; + dispatch(EventType.REFERENCE_CHANGED); + }}> ${ batch.index === referenceBatch.index ? html`reference` : html``} - `)} - `; + `)} + `; } private renderSentence() { @@ -128,7 +129,7 @@ export class CodecCompare extends LitElement { private renderTruncatedResults() { return html`
- warning + warning

The results are partial because there are too many possible comparisons. Consider filtering input rows out. @@ -203,40 +204,45 @@ export class CodecCompare extends LitElement { ${displaySentence ? this.renderSentence() : ''} ${displayGallery ? this.renderGallery() : ''} - ) => { - this.currentTab = event.detail.index; - this.requestUpdate(); + { + if (event.target instanceof MdTabs) { + this.currentTab = event.target.activeTabIndex; + this.requestUpdate(); + } }}> - - - - - + short_textSummary + tuneAdvanced + photo_libraryData set +

- { + { navigator.clipboard.writeText(window.location.href); }}> - share Copy URL to clipboard - + Copy URL to clipboard + share + - - settings Settings - + + Settings + settings + - { + { this.helpUi.onOpen(); }}> - help Help - + Help + help + - - open_in_new Resources - + + Resources + open_in_new +

@@ -252,7 +258,7 @@ export class CodecCompare extends LitElement {

- Codec Compare version 0.6.6
+ Codec Compare version 0.7.0
Sources on GitHub @@ -358,11 +364,11 @@ export class CodecCompare extends LitElement { } p { margin: 0; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); font-size: 20px; } - mwc-tab-bar { + md-tabs { position: absolute; top: 0; left: 60px; /* Width of #leftBar. */ @@ -403,8 +409,8 @@ export class CodecCompare extends LitElement { overflow-y: auto; overflow-x: hidden; } - mwc-tab-bar, #sentenceContainer, #galleryContainer, #advancedInterfaceContainerContainer { - background: var(--mdc-theme-surface); + md-tabs, #sentenceContainer, #galleryContainer, #advancedInterfaceContainerContainer { + background: var(--md-sys-color-surface); /* Simulate the shadow of the plot on the right. */ box-shadow: inset -4px 0 8px 0 rgba(0, 0, 0, 0.2); } @@ -415,22 +421,23 @@ export class CodecCompare extends LitElement { cursor: pointer; } #referenceButton { - --mdc-theme-primary: white; - --mdc-theme-on-primary: var(--mdc-theme-text); - vertical-align: middle; + --md-sys-color-primary: var(--md-sys-color-background); + --md-sys-color-on-primary: var(--md-sys-color-text); } #referenceButton batch-name-ui { - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); font-size: 16px; white-space: nowrap; - text-transform: none; + /* text-transform: none; */ } #referenceMenu { - --mdc-menu-item-height: 20px; + --md-menu-item-one-line-container-height: 20px; + --md-menu-item-top-space: 0; + --md-menu-item-bottom-space: 0; } .referenceBatchChip { - background: var(--mdc-theme-primary); - color: var(--mdc-theme-background); + background: var(--md-sys-color-primary); + color: var(--md-sys-color-background); border-radius: 16px; padding: 2px 8px; font-size: 12px; @@ -443,9 +450,9 @@ export class CodecCompare extends LitElement { display: flex; align-items: center; gap: 16px; - --mdc-icon-size: 64px; + --md-icon-size: 64px; } - #truncatedResults mwc-icon, #truncatedResults p { + #truncatedResults md-icon, #truncatedResults p { color: white; } @@ -469,40 +476,44 @@ export class CodecCompare extends LitElement { left: 0; bottom: 0; width: 500px; - background: var(--mdc-theme-primary); + background: var(--md-sys-color-primary); padding: 6px; display: flex; flex-direction: column; align-items: flex-start; gap: 12px; + /* Otherwise the active tab goes in front of the left bar. */ + z-index: 1; } - #leftBarContent > mwc-button-fit { - --mdc-theme-primary: var(--mdc-theme-background); - --mdc-typography-button-font-size: 20px; - } - #leftBarContent > mwc-button-fit > mwc-icon { - font-size: 42px; - margin-right: 16px; + #leftBarContent > md-filled-button { + --md-filled-button-container-height: 50px; + --md-filled-button-label-text-line-height: 24px; + --md-filled-button-label-text-size: 24px; + --md-filled-button-icon-size: 32px; + --md-filled-button-container-color: var(--md-sys-color-primary); + --md-filled-button-disabled-container-color: var(--md-sys-color-primary); + overflow: visible; + --md-filled-button-container-shape: 0px; } #presets { margin-left: 70px; - color: var(--mdc-theme-background); + color: var(--md-sys-color-background); font-family: Roboto, sans-serif; font-size: 16px; } #presets > a { - color: var(--mdc-theme-background); + color: var(--md-sys-color-background); } #credits { margin-left: 70px; margin-top: auto; font-size: 16px; - color: var(--mdc-theme-background); + color: var(--md-sys-color-background); } #credits > a { - color: var(--mdc-theme-background); + color: var(--md-sys-color-background); } `; } diff --git a/src/color_setter.ts b/src/color_setter.ts index 82ce76c..b3c19d3 100644 --- a/src/color_setter.ts +++ b/src/color_setter.ts @@ -39,7 +39,7 @@ export function setColors(state: State) { let hue = 0.85 * groupIndex / (state.groups.length + 1); // Skip pure red which looks ominous. hue += 0.05; - // Skip colors close to --mdc-theme-primary. + // Skip colors close to --md-sys-color-primary. if (hue > 0.63) hue += 0.10; // Slightly greyish to avoid burning eyes. const saturation = 0.8; diff --git a/src/constant_test.ts b/src/constant_test.ts index ee12d5a..944f437 100644 --- a/src/constant_test.ts +++ b/src/constant_test.ts @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'jasmine'; - import {getFinalConstantValues} from './constant'; import {Batch, Constant, Field} from './entry'; diff --git a/src/constants_table_ui.ts b/src/constants_table_ui.ts index 87e2895..f21cf63 100644 --- a/src/constants_table_ui.ts +++ b/src/constants_table_ui.ts @@ -98,7 +98,7 @@ export class ConstantsTableUi extends LitElement { } table { - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); border-collapse: collapse; min-width: 100%; } @@ -109,16 +109,16 @@ export class ConstantsTableUi extends LitElement { border-style: solid; } th { - border-color: var(--mdc-theme-background); - background: var(--mdc-theme-surface); + border-color: var(--md-sys-color-background); + background: var(--md-sys-color-surface); } td { - border-color: var(--mdc-theme-surface); + border-color: var(--md-sys-color-surface); font-family: monospace; word-break: break-word; } tr { - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); } .description { font-style: italic; diff --git a/src/copy_button.ts b/src/copy_button.ts index c1b12b6..165ae29 100644 --- a/src/copy_button.ts +++ b/src/copy_button.ts @@ -12,50 +12,38 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-icon-button'; -import '@material/mwc-snackbar'; +import '@material/web/iconbutton/filled-icon-button'; +import '@material/web/icon/icon'; -import {Snackbar} from '@material/mwc-snackbar'; import {css, html, LitElement} from 'lit'; -import {customElement, property, query} from 'lit/decorators.js'; +import {customElement, property} from 'lit/decorators.js'; /** Component that copies text to the clipboard when clicked. */ @customElement('copy-button') export class CopyButton extends LitElement { @property() textToCopyInClipboard!: string; - // There should be only one snackbar per page but one snackbar per CopyButton - // is easier to reference. - @query('mwc-snackbar') private readonly snackbar!: Snackbar; - override render() { return html` - { if (window.isSecureContext) { navigator.clipboard.writeText(this.textToCopyInClipboard); - this.snackbar.labelText = 'Copied to clipboard'; - this.snackbar.show(); - } else { - this.snackbar.labelText = 'Copy to clipboard failed'; - this.snackbar.show(); } }}> - - `; + content_copy + `; } static override styles = css` :host { float: right; } - mwc-icon-button { - color: var(--mdc-theme-text); - /* Make the background disk that appears when hovered slightly bigger - * than the icon itself, which is 24px. */ - --mdc-icon-button-size: 28px; - /* Tighten the buttons to save space. */ - margin: -2px; + md-filled-icon-button { + --md-filled-icon-button-icon-size: 20px; + --md-filled-icon-button-container-width: 24px; + --md-filled-icon-button-container-height: 24px; + overflow: hidden; } `; } diff --git a/src/entry_loader_test.ts b/src/entry_loader_test.ts index 4d79d9e..bd1132f 100644 --- a/src/entry_loader_test.ts +++ b/src/entry_loader_test.ts @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'jasmine'; - import {FieldId} from './entry'; import {loadBatchJson, loadJsonContainingBatchJsonPaths} from './entry_loader'; diff --git a/src/fields_table_ui.ts b/src/fields_table_ui.ts index e39c9c0..cc09022 100644 --- a/src/fields_table_ui.ts +++ b/src/fields_table_ui.ts @@ -61,7 +61,7 @@ export class FieldsTableUi extends LitElement { } table { - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); border-collapse: collapse; min-width: 100%; } @@ -72,16 +72,16 @@ export class FieldsTableUi extends LitElement { border-style: solid; } th { - border-color: var(--mdc-theme-background); - background: var(--mdc-theme-surface); + border-color: var(--md-sys-color-background); + background: var(--md-sys-color-surface); } td { - border-color: var(--mdc-theme-surface); + border-color: var(--md-sys-color-surface); font-family: monospace; word-break: break-word; } tr { - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); } .description { font-style: italic; diff --git a/src/filter_generic_ui.ts b/src/filter_generic_ui.ts index a820aad..fd761c2 100644 --- a/src/filter_generic_ui.ts +++ b/src/filter_generic_ui.ts @@ -12,16 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-button'; -import '@material/mwc-checkbox'; -import '@material/mwc-slider'; -import '@material/mwc-slider/slider-range'; -import '@material/mwc-textfield'; +import '@material/web/button/filled-button'; +import '@material/web/icon/icon'; -import {SliderRange} from '@material/mwc-slider/slider-range'; -import {TextField} from '@material/mwc-textfield'; import {css, html, LitElement} from 'lit'; -import {customElement, property, query} from 'lit/decorators.js'; +import {customElement, property} from 'lit/decorators.js'; import {Field} from './entry'; import {dispatch, EventType, listen} from './events'; @@ -41,23 +36,21 @@ export class FilterUiGeneric extends LitElement { ${this.filter.toString(this.field, /*short=*/ false)}

- { this.filter.enabled = false; dispatch(EventType.FILTER_CHANGED, {batchIndex: this.batchIndex}); }} title="Delete filter"> - filter_alt_off - + filter_alt_off + `; } static override styles = css` :host { display: block; - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); margin: 0; padding: 10px; border-radius: 10px; @@ -71,9 +64,16 @@ export class FilterUiGeneric extends LitElement { p { margin: 0; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); font-size: 20px; white-space: nowrap; } + + md-filled-icon-button { + --md-filled-icon-button-icon-size: 24px; + --md-filled-icon-button-container-width: 32px; + --md-filled-icon-button-container-height: 32px; + overflow: hidden; + } `; } diff --git a/src/filter_range_ui.ts b/src/filter_range_ui.ts index 6c9d8b3..62a745b 100644 --- a/src/filter_range_ui.ts +++ b/src/filter_range_ui.ts @@ -12,13 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-button'; -import '@material/mwc-slider'; -import '@material/mwc-slider/slider-range'; -import '@material/mwc-textfield'; +import '@material/web/button/filled-button'; +import '@material/web/textfield/outlined-text-field'; +import '@material/web/slider/slider'; +import '@material/web/icon/icon'; -import {SliderRange} from '@material/mwc-slider/slider-range'; -import {TextField} from '@material/mwc-textfield'; +import {MdSlider} from '@material/web/slider/slider'; +import {MdOutlinedTextField} from '@material/web/textfield/outlined-text-field'; import {css, html, LitElement} from 'lit'; import {customElement, property, query} from 'lit/decorators.js'; @@ -33,21 +33,9 @@ export class FilterUiRange extends LitElement { @property({attribute: false}) field!: Field; @property({attribute: false}) filter!: FieldFilterRange; - @query('#numberMin') private readonly numberMin?: TextField; - @query('#numberMax') private readonly numberMax?: TextField; - @query('#numberSlider') private readonly numberSlider?: SliderRange; - - override connectedCallback() { - super.connectedCallback(); - // Hack to force refreshing the mwc-slider-range. Otherwise it may appear - // broken (probably due to being initialized in a display:none parent). - listen(EventType.FILTERED_DATA_INFO_REQUEST, async () => { - await new Promise(r => setTimeout(r, 1)); - if (this.numberSlider !== undefined) { - await this.numberSlider.layout(); - } - }); - } + @query('#numberMin') private readonly numberMin?: MdOutlinedTextField; + @query('#numberMax') private readonly numberMax?: MdOutlinedTextField; + @query('#numberSlider') private readonly numberSlider?: MdSlider; private renderSingleUniqueValue() { const uniqueValue = this.field.uniqueValuesArray.length === 0 ? @@ -77,9 +65,9 @@ export class FilterUiRange extends LitElement { }; return html` - - `; + `; } private renderNumberMax() { @@ -98,9 +86,9 @@ export class FilterUiRange extends LitElement { }; return html` - - `; + `; } private renderNumberSlider() { @@ -110,12 +98,12 @@ export class FilterUiRange extends LitElement { if (this.numberSlider === undefined) return; if (this.numberSlider.valueStart !== this.filter.rangeStart) { - this.filter.rangeStart = this.numberSlider.valueStart; + this.filter.rangeStart = this.numberSlider.valueStart!; this.numberMin.value = this.filter.rangeStart.toString(); dispatch(EventType.FILTER_CHANGED, {batchIndex: this.batchIndex}); } if (this.numberSlider.valueEnd !== this.filter.rangeEnd) { - this.filter.rangeEnd = this.numberSlider.valueEnd; + this.filter.rangeEnd = this.numberSlider.valueEnd!; this.numberMax.value = this.filter.rangeEnd.toString(); dispatch(EventType.FILTER_CHANGED, {batchIndex: this.batchIndex}); } @@ -125,44 +113,43 @@ export class FilterUiRange extends LitElement { if (this.field.isInteger) { if (range < 30) { // withtickmarks is laggy with large values - return html``; + id="numberSlider">`; } - return html``; + id="numberSlider">`; } - // Hack to bypass the inconvenient check at - // https://github.com/simonziegler/material-components-web/blob/78305b6d547b07aa06db04ad47b765b8f92851fa/packages/mdc-slider/foundation.ts#L1017-L1025 const step = range / (256 * 256); const min = this.field.rangeStart; const valueStart = min + Math.round((this.filter.rangeStart - min) / step) * step; const valueEnd = min + Math.round((this.filter.rangeEnd - min) / step) * step; - return html``; + id="numberSlider">`; } private renderNumber() { @@ -184,23 +171,21 @@ export class FilterUiRange extends LitElement { this.field.uniqueValuesArray.length < 2 ? this.renderSingleUniqueValue() : this.renderNumber()} - { this.filter.enabled = false; dispatch(EventType.FILTER_CHANGED, {batchIndex: this.batchIndex}); }} title="Delete filter"> - filter_alt_off - + filter_alt_off + `; } static override styles = css` :host { display: block; - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); margin: 0; padding: 10px; border-radius: 10px; @@ -214,17 +199,28 @@ export class FilterUiRange extends LitElement { p { margin: 0; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); font-size: 20px; white-space: nowrap; } - mwc-textfield { + md-outlined-text-field { width: 80px; height: 35px; + --md-outlined-field-top-space: 2px; + --md-outlined-field-bottom-space: 2px; + --md-outlined-text-field-leading-space: 2px; + --md-outlined-text-field-trailing-space: 2px; } - mwc-slider-range { + md-slider { width: 400px; } + + md-filled-icon-button { + --md-filled-icon-button-icon-size: 24px; + --md-filled-icon-button-container-width: 32px; + --md-filled-icon-button-container-height: 32px; + overflow: hidden; + } `; } diff --git a/src/filter_ranges_test.ts b/src/filter_ranges_test.ts index e0cb288..7bc391a 100644 --- a/src/filter_ranges_test.ts +++ b/src/filter_ranges_test.ts @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'jasmine'; - import {FieldFilterWebBppJpeg} from './filter_ranges'; describe('FieldFilterWebBppJpeg', () => { diff --git a/src/filter_string_set_ui.ts b/src/filter_string_set_ui.ts index 8085573..d5fc80f 100644 --- a/src/filter_string_set_ui.ts +++ b/src/filter_string_set_ui.ts @@ -12,11 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-button'; -import '@material/mwc-checkbox'; +import '@material/web/button/filled-button'; +import '@material/web/checkbox/checkbox'; +import '@material/web/icon/icon'; import {css, html, LitElement} from 'lit'; -import {customElement, property, query} from 'lit/decorators.js'; +import {customElement, property} from 'lit/decorators.js'; import {Field} from './entry'; import {dispatch, EventType, listen} from './events'; @@ -54,9 +55,9 @@ export class FilterUiStringSet extends LitElement { return html` `; } @@ -79,23 +80,21 @@ export class FilterUiStringSet extends LitElement { this.field.uniqueValuesArray.length < 2 ? this.renderSingleUniqueValue() : this.renderList()} - { this.filter.enabled = false; dispatch(EventType.FILTER_CHANGED, {batchIndex: this.batchIndex}); }} title="Delete filter"> - filter_alt_off - + filter_alt_off + `; } static override styles = css` :host { display: block; - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); margin: 0; padding: 10px; border-radius: 10px; @@ -109,7 +108,7 @@ export class FilterUiStringSet extends LitElement { p { margin: 0; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); font-size: 20px; white-space: nowrap; } @@ -120,10 +119,17 @@ export class FilterUiStringSet extends LitElement { align-items: center; justify-content: center; white-space: nowrap; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); font-family: monospace; - background: var(--mdc-theme-surface); + background: var(--md-sys-color-surface); border-radius: 30px; } + + md-filled-icon-button { + --md-filled-icon-button-icon-size: 24px; + --md-filled-icon-button-container-width: 32px; + --md-filled-icon-button-container-height: 32px; + overflow: hidden; + } `; } diff --git a/src/filter_web_bpp_ui.ts b/src/filter_web_bpp_ui.ts index 1f38384..c51d1e0 100644 --- a/src/filter_web_bpp_ui.ts +++ b/src/filter_web_bpp_ui.ts @@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-button'; -import '@material/mwc-textfield'; +import '@material/web/button/filled-button'; +import '@material/web/icon/icon'; import {css, html, LitElement} from 'lit'; -import {customElement, property, query} from 'lit/decorators.js'; +import {customElement, property} from 'lit/decorators.js'; import {Field} from './entry'; import {dispatch, EventType, listen} from './events'; @@ -39,7 +39,7 @@ export class FilterUiWebBpp extends LitElement { Megapixels buckets as described at Bits-per-pixel of Internet images - open_in_new: + open_in_new:

@@ -60,23 +60,21 @@ export class FilterUiWebBpp extends LitElement { bucket[BUCKET_FILTER_MAX_INCLUSIVE].toFixed(2)}]`)}
- { this.filter.enabled = false; dispatch(EventType.FILTER_CHANGED, {batchIndex: this.batchIndex}); }} title="Delete filter"> - filter_alt_off - + filter_alt_off + `; } static override styles = css` :host { display: block; - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); margin: 0; padding: 10px; border-radius: 10px; @@ -90,11 +88,18 @@ export class FilterUiWebBpp extends LitElement { p { margin: 0; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); font-size: 20px; } - mwc-icon { + md-icon { vertical-align: top; } + + md-filled-icon-button { + --md-filled-icon-button-icon-size: 24px; + --md-filled-icon-button-container-width: 32px; + --md-filled-icon-button-container-height: 32px; + overflow: hidden; + } `; } diff --git a/src/filtered_images_ui.ts b/src/filtered_images_ui.ts index dcbb61b..017d630 100644 --- a/src/filtered_images_ui.ts +++ b/src/filtered_images_ui.ts @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-icon'; -import '@material/mwc-button'; +import '@material/web/icon/icon'; import {css, html, LitElement} from 'lit'; import {customElement, property} from 'lit/decorators.js'; @@ -75,7 +74,7 @@ export class FilteredImagesUi extends LitElement { return html`
- photo_library + photo_library ${this.batchSelection.filteredRowIndices.length} / ${ batch.rows.length}
@@ -112,8 +111,8 @@ export class FilteredImagesUi extends LitElement { padding: 0 15px; height: 40px; border-radius: 30px; - background: var(--mdc-theme-primary); - color: var(--mdc-theme-background); + background: var(--md-sys-color-primary); + color: var(--md-sys-color-background); display: flex; align-items: center; gap: 5px; @@ -121,7 +120,7 @@ export class FilteredImagesUi extends LitElement { } h2 { margin: 0; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); } .tableParent { @@ -136,7 +135,7 @@ export class FilteredImagesUi extends LitElement { } table { - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); width: 100%; white-space: nowrap; border-collapse: collapse; @@ -148,24 +147,24 @@ export class FilteredImagesUi extends LitElement { border-style: solid; } th { - border-color: var(--mdc-theme-background); - background: var(--mdc-theme-surface); + border-color: var(--md-sys-color-background); + background: var(--md-sys-color-surface); font-size: 12px; position: sticky; top: 0; border-top: 0; } td { - border-color: var(--mdc-theme-surface); + border-color: var(--md-sys-color-surface); font-family: monospace; font-size: 10px; } tr { - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); } tr:hover { - background: var(--mdc-theme-surface); + background: var(--md-sys-color-surface); } .excluded { color: grey; diff --git a/src/filters_ui.ts b/src/filters_ui.ts index e9265ce..2699f21 100644 --- a/src/filters_ui.ts +++ b/src/filters_ui.ts @@ -12,17 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-menu'; -import '@material/mwc-icon'; -import '@material/mwc-button'; +import '@material/web/menu/menu'; +import '@material/web/menu/menu-item'; +import '@material/web/icon/icon'; +import '@material/web/button/filled-button'; import './filter_generic_ui'; import './filter_range_ui'; import './filter_string_set_ui'; import './filter_web_bpp_ui'; -import {Button} from '@material/mwc-button'; -import {ActionDetail} from '@material/mwc-list'; -import {Menu} from '@material/mwc-menu'; +import {MdFilledButton} from '@material/web/button/filled-button'; +import {MdMenu} from '@material/web/menu/menu'; +import {MenuItem} from '@material/web/menu/menu-item'; import {css, html, LitElement} from 'lit'; import {customElement, property, query} from 'lit/decorators.js'; @@ -39,8 +40,8 @@ export class FiltersUi extends LitElement { @property({attribute: false}) state!: State; @property() batchSelection!: BatchSelection; - @query('#addFilterMenu') private readonly addFilterMenu!: Menu; - @query('#addFilterButton') private readonly addFilterButton!: Button; + @query('#addFilterMenu') private readonly addFilterMenu!: MdMenu; + @query('#addFilterButton') private readonly addFilterButton!: MdFilledButton; private readonly onFilterChanged = (event: CustomEvent) => { if (event.detail.batchIndex === this.batchSelection.batch.index) { @@ -59,41 +60,38 @@ export class FiltersUi extends LitElement { private renderAddFilterMenu() { const batch = this.batchSelection.batch; return html` - { - this.addFilterMenu.show(); + this.addFilterMenu.open = !this.addFilterMenu.open; }} title="Add filter" id="addFilterButton"> - add - filter_alt - - ) => { - this.batchSelection.fieldFilters[e.detail.index].fieldFilter.enabled = - true; - dispatch( - EventType.FILTER_CHANGED, - {batchIndex: this.batchSelection.batch.index}); - }}> + add + filter_alt + + ${ this.batchSelection.fieldFilters.map( (filter: FieldFilterWithIndex) => filter.fieldFilter.enabled ? - html` + html` ${ filter.fieldFilter.displayName( batch.fields[filter.fieldIndex])} - ` : - html` + ` : + html` { + filter.fieldFilter.enabled = true; + dispatch( + EventType.FILTER_CHANGED, + {batchIndex: this.batchSelection.batch.index}); + }}> ${ filter.fieldFilter.displayName( batch.fields[filter.fieldIndex])} - `)} - + `)} + `; } @@ -147,7 +145,7 @@ export class FiltersUi extends LitElement { return html`
- filter_alt + filter_alt ${numEnabledFilters}

active filters

@@ -181,8 +179,8 @@ export class FiltersUi extends LitElement { padding: 0 15px; height: 40px; border-radius: 30px; - background: var(--mdc-theme-primary); - color: var(--mdc-theme-background); + background: var(--md-sys-color-primary); + color: var(--md-sys-color-background); display: flex; align-items: center; gap: 5px; @@ -190,23 +188,30 @@ export class FiltersUi extends LitElement { } h2 { margin: 0; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); } #addFilterParent { - /* mwc-menu and its anchor need a parent with position set to relative. */ + /* md-menu and its anchor need a parent with position set to relative. */ position: relative; } - mwc-menu { + #addFilterButton { + --md-filled-button-label-text-line-height: 1em; + --md-filled-button-container-height: 32px; + } + md-menu { /* Otherwise the menu is clipped by the parent's overflow:hidden. * Unfortunately this prevents the menu from properly reducing in height * when there is not enough space to display all items. */ position: fixed; /* This way all items should fit on screen. */ - --mdc-menu-item-height: 20px; - /* Otherwise the menu is rendered under the mwc checkboxes. */ + --md-menu-item-one-line-container-height: 20px; + --md-menu-item-top-space: 0; + --md-menu-item-bottom-space: 0; + /* Otherwise the menu is rendered under the md checkboxes. */ z-index: 6; + white-space: nowrap; } .menuItemDisabled { color: grey; diff --git a/src/gallery_ui.ts b/src/gallery_ui.ts index 8696012..2d2d247 100644 --- a/src/gallery_ui.ts +++ b/src/gallery_ui.ts @@ -12,7 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-icon'; +import '@material/web/button/filled-button'; +import '@material/web/checkbox/checkbox'; +import '@material/web/icon/icon'; import './batch_name_ui'; import './matcher_ui'; @@ -110,34 +112,34 @@ export class GalleryUi extends LitElement { ${Array.from(this.tagToAssetNames.keys()).map(tag => html` - addTag(tag)} + addTag(tag)} title="Enable all assets tagged as ${tag}"> - add + add ${tag} - + - removeTag(tag)} + removeTag(tag)} title="Disable all assets tagged as ${tag}"> - remove + remove ${tag} - + `)} - - add + add All - + - - remove + remove All - + `; @@ -177,9 +179,9 @@ export class GalleryUi extends LitElement { ${asset.sourceName} ${asset.count} -
open_in_new
- - +
open_in_new
+ + `; } @@ -200,9 +202,9 @@ export class GalleryUi extends LitElement { ${asset.sourceName} ${asset.count} -
open_in_new
- - +
open_in_new
+ + `; } return html` @@ -241,7 +243,7 @@ export class GalleryUi extends LitElement { } table { - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); border-collapse: collapse; box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.2); } @@ -252,16 +254,16 @@ export class GalleryUi extends LitElement { border-style: solid; } th { - border-color: var(--mdc-theme-background); - background: var(--mdc-theme-surface); + border-color: var(--md-sys-color-background); + background: var(--md-sys-color-surface); } td { - border-color: var(--mdc-theme-surface); + border-color: var(--md-sys-color-surface); font-family: monospace; word-break: break-word; } tr { - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); } #tags td { @@ -283,7 +285,7 @@ export class GalleryUi extends LitElement { overflow: hidden; overflow-wrap: break-word; text-align: center; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 4px 0px; } #gallery > a { @@ -317,12 +319,12 @@ export class GalleryUi extends LitElement { .linkOverlay:hover{ opacity: 1; } - .linkOverlay > mwc-icon { - color: var(--mdc-theme-background); + .linkOverlay > md-icon { + color: var(--md-sys-color-background); font-size: 16px; } - mwc-checkbox { + md-checkbox { position: absolute; top: 0; left: 0; @@ -339,8 +341,8 @@ export class GalleryUi extends LitElement { padding: 2px 4px; border-radius: 3px; font-size: 12px; - color: var(--mdc-theme-background); - background: var(--mdc-theme-primary); + color: var(--md-sys-color-background); + background: var(--md-sys-color-primary); } `; } diff --git a/src/help_ui.ts b/src/help_ui.ts index 1f467c3..ae603cd 100644 --- a/src/help_ui.ts +++ b/src/help_ui.ts @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-fab'; -import '@material/mwc-icon'; +import '@material/web/fab/fab'; +import '@material/web/icon/icon'; import {css, html, LitElement} from 'lit'; import {customElement, property, query} from 'lit/decorators.js'; @@ -199,7 +199,7 @@ export class HelpUi extends LitElement { bits-per-pixel usually seen on the web - open_in_new.
+ open_in_new.
Click the visibility button to show or hide a specific batch in the plot and in the SUMMARY tab.
${ this.rdMode ? html` @@ -229,9 +229,9 @@ export class HelpUi extends LitElement { matched pairs based on that asset accross all batches.`}
Each image can be toggled on or off across all batches.

Images can be toggled on or off in bulk using the filter tags.
- "addTAG" enables all images associated with that + "addTAG" enables all images associated with that TAG.
- "removeTAG" disables all images associated with that + "removeTAG" disables all images associated with that TAG.

`; @@ -270,18 +270,18 @@ export class HelpUi extends LitElement { For an introduction to image file formats, please see this - Wikipedia article open_in_new. + Wikipedia article open_in_new.
For any question or comment on this tool, please open an issue on - GitHub open_in_new. + GitHub open_in_new.

- - + + close + `; } @@ -340,9 +340,9 @@ export class HelpUi extends LitElement { a { color: white; } - - mwc-icon { - font-size: 0.8em; + md-icon { + vertical-align: middle; + --md-icon-size: 1em; } `; } \ No newline at end of file diff --git a/src/histogram_test.ts b/src/histogram_test.ts index 47680a0..0c24727 100644 --- a/src/histogram_test.ts +++ b/src/histogram_test.ts @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'jasmine'; - import {mergeHistograms} from './batch_merger'; import {BatchSelection} from './batch_selection'; import {Batch, Field, FieldId} from './entry'; diff --git a/src/loading_ui.ts b/src/loading_ui.ts index 746fe47..33b079f 100644 --- a/src/loading_ui.ts +++ b/src/loading_ui.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-linear-progress'; +import '@material/web/progress/linear-progress'; import {css, html, LitElement} from 'lit'; import {customElement, property} from 'lit/decorators.js'; @@ -25,14 +25,11 @@ export class LoadingUi extends LitElement { @property({type: Number}) progress = 0; override render() { - const progressFirstHalf = Math.min(1, this.progress * 2); - const progressSecondHalf = Math.max(0, this.progress * 2 - 1); return html`

${this.text}

- - + +
`; } @@ -49,7 +46,7 @@ export class LoadingUi extends LitElement { align-items: center; overflow: hidden; z-index: 10; - background: var(--mdc-theme-surface); + background: var(--md-sys-color-surface); opacity: 1; transition: opacity 0.3s; cursor: wait; @@ -57,7 +54,7 @@ export class LoadingUi extends LitElement { .card { padding: 16px; - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.2); border-radius: 20px; display: flex; @@ -70,7 +67,7 @@ export class LoadingUi extends LitElement { p { margin: 10px; padding: 0; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); font-size: 26px; } `; diff --git a/src/match_image_ui.ts b/src/match_image_ui.ts index c4e6f54..a0ac068 100644 --- a/src/match_image_ui.ts +++ b/src/match_image_ui.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-icon'; +import '@material/web/icon/icon'; import './batch_name_ui'; import './filtered_images_ui'; import './filters_ui'; @@ -86,8 +86,8 @@ export class MatchImageUi extends LitElement {
- ${compare ? 'compare' : 'image'} - open_in_new + ${compare ? 'compare' : 'image'} + open_in_new
`; } @@ -134,8 +134,8 @@ export class MatchImageUi extends LitElement { #imageOverlay:hover{ opacity: 1; } - #imageOverlay > mwc-icon { - color: var(--mdc-theme-background); + #imageOverlay > md-icon { + color: var(--md-sys-color-background); font-size: 26px; } `; diff --git a/src/match_test.ts b/src/match_test.ts index 3cf9e62..33a34f0 100644 --- a/src/match_test.ts +++ b/src/match_test.ts @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'jasmine'; - import {Batch, Field} from './entry'; import {getDataPoints, getDataPointsSymmetric, Match} from './matcher'; import {State} from './state'; diff --git a/src/matcher_ui.ts b/src/matcher_ui.ts index 73fcc97..7436d12 100644 --- a/src/matcher_ui.ts +++ b/src/matcher_ui.ts @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-menu'; -import './mwc_button_fit'; +import '@material/web/menu/menu'; +import '@material/web/menu/menu-item'; +import '@material/web/icon/icon'; import './tooltip_ui'; -import {Button} from '@material/mwc-button'; -import {Menu} from '@material/mwc-menu'; +import {MdMenu} from '@material/web/menu/menu'; import {css, html, LitElement} from 'lit'; import {customElement, property, query} from 'lit/decorators.js'; @@ -41,67 +41,66 @@ export class MatcherUi extends LitElement { private readonly AVAILABLE_TOLERANCE = [0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.10, 0.20]; - @query('#toleranceButton') private readonly toleranceButton!: Button; - @query('#toleranceMenu') private readonly toleranceMenu!: Menu; + @query('#toleranceButton') private readonly toleranceButton!: any; + @query('#toleranceMenu') private readonly toleranceMenu!: MdMenu; private renderToleranceButton() { if (!this.isNumber) { return html``; } - // mwc-menu and its anchor need a parent with position set to relative. + // md-menu and its anchor need a parent with position set to relative. return html` - { - this.toleranceMenu.show(); - }} - id="toleranceButton"> - { - this.matcher.tolerance = this.AVAILABLE_TOLERANCE[e.detail.index]; - dispatch(EventType.MATCHER_OR_METRIC_CHANGED); - this.requestUpdate(); + this.toleranceMenu.open = !this.toleranceMenu.open; }} + id="toleranceButton"> + ${toleranceRangePercent(this.matcher.tolerance)} + + - ${this.AVAILABLE_TOLERANCE.map((availableTolerance: number) => html` - + ${ + this.AVAILABLE_TOLERANCE.map( + (availableTolerance: number) => html` + { + this.matcher.tolerance = availableTolerance; + dispatch(EventType.MATCHER_OR_METRIC_CHANGED); + this.requestUpdate(); + }}> Set tolerance to ${toleranceRangePercent(availableTolerance)} - `)} - + `)} + `; } private renderDeleteButton() { if (this.fieldId === FieldId.SOURCE_IMAGE_NAME) { - // title on a disabled mwc-button-fit does not work. Encapsulate in a div. + // title on a disabled button does not work. Encapsulate in a div. return html`
- delete + + delete +
`; } return html` - { this.matcher.enabled = false; dispatch(EventType.MATCHER_OR_METRIC_CHANGED); }} title="Delete matcher"> - delete - `; + delete + `; } override render() { @@ -133,7 +132,7 @@ export class MatcherUi extends LitElement { static override styles = css` :host { - background-color: var(--mdc-theme-surface); + background-color: var(--md-sys-color-surface); margin: 0; padding: 6px; border-radius: 6px; @@ -144,12 +143,29 @@ export class MatcherUi extends LitElement { } p { margin: 0; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); font-size: 20px; } - mwc-icon { - font-size: 20px; + #toleranceButton { + --md-filled-button-container-height: 20px; + --md-filled-button-label-text-size: 14px; + --md-filled-button-leading-space: 4px; + --md-filled-button-trailing-space: 4px; + --md-filled-button-container-shape: 2px; + } + + md-filled-icon-button { + --md-filled-icon-button-icon-size: 20px; + --md-filled-icon-button-container-width: 24px; + --md-filled-icon-button-container-height: 24px; + } + + md-menu-item { + --md-menu-item-one-line-container-height: 20px; + --md-menu-item-top-space: 0; + --md-menu-item-bottom-space: 0; + white-space: nowrap; } `; } diff --git a/src/matchers_ui.ts b/src/matchers_ui.ts index a4b67f5..a0c1fe8 100644 --- a/src/matchers_ui.ts +++ b/src/matchers_ui.ts @@ -12,13 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-fab'; -import '@material/mwc-menu'; +import '@material/web/fab/fab'; +import '@material/web/menu/menu'; +import '@material/web/menu/menu-item'; +import '@material/web/icon/icon'; import './matcher_ui'; -import {Fab} from '@material/mwc-fab'; -import {ActionDetail} from '@material/mwc-list'; -import {Menu} from '@material/mwc-menu'; +import {MdFab} from '@material/web/fab/fab'; +import {MdMenu} from '@material/web/menu/menu'; +import {MenuItem} from '@material/web/menu/menu-item'; import {css, html, LitElement} from 'lit'; import {customElement, property, query} from 'lit/decorators.js'; @@ -32,8 +34,8 @@ import {State} from './state'; export class MatchersUi extends LitElement { @property({attribute: false}) state!: State; - @query('#addMatcherMenu') private readonly addMatcherMenu!: Menu; - @query('#addMatcherButton') private readonly addMatcherButton!: Fab; + @query('#addMatcherMenu') private readonly addMatcherMenu!: MdMenu; + @query('#addMatcherButton') private readonly addMatcherButton!: MdFab; override connectedCallback() { super.connectedCallback(); @@ -47,34 +49,31 @@ export class MatchersUi extends LitElement { const fieldName = this.state.batches[0].fields[matcher.fieldIndices[0]].displayName; return matcher.enabled ? - html`${fieldName}` : - html`${fieldName}`; + html` + ${fieldName}` : + html`) => { + matcher.enabled = true; + dispatch(EventType.MATCHER_OR_METRIC_CHANGED); + }}>${fieldName}`; })}`; } private renderAddMatcherMenu() { - // mwc-menu and its anchor need a parent with position set to relative. + // md-menu and its anchor need a parent with position set to relative. return html` - { - this.addMatcherMenu.show(); + this.addMatcherMenu.open = !this.addMatcherMenu.open; }} - id="addMatcherButton"> - ) => { - this.state.matchers[e.detail.index].enabled = true; - dispatch(EventType.MATCHER_OR_METRIC_CHANGED); - }}> + id="addMatcherButton"> + add + + ${this.renderAddMatcherMenuItems()} - + `; } @@ -122,7 +121,7 @@ export class MatchersUi extends LitElement { static override styles = css` :host { - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); padding: 6px; box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.2); border-radius: 16px; @@ -138,13 +137,16 @@ export class MatchersUi extends LitElement { margin-left: auto; } - .menuItemDisabled { - color: grey; + #addMatcherButton { + --md-fab-container-width: 32px; + --md-fab-container-height: 32px; + --md-fab-icon-size: 20px; } - #addMatcherButton { - /* Save screen space. */ - margin: -6px; + md-menu-item { + --md-menu-item-one-line-container-height: 20px; + --md-menu-item-top-space: 0; + --md-menu-item-bottom-space: 0; } `; } diff --git a/src/matches_table_ui.ts b/src/matches_table_ui.ts index 1930e74..e5ec6c9 100644 --- a/src/matches_table_ui.ts +++ b/src/matches_table_ui.ts @@ -519,7 +519,7 @@ export class MatchesTableUi extends LitElement { } table { - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); width: 100%; white-space: nowrap; border-collapse: collapse; @@ -531,8 +531,8 @@ export class MatchesTableUi extends LitElement { border-style: solid; } th { - border-color: var(--mdc-theme-background); - background: var(--mdc-theme-surface); + border-color: var(--md-sys-color-background); + background: var(--md-sys-color-surface); font-size: 12px; } .headerRow { @@ -541,7 +541,7 @@ export class MatchesTableUi extends LitElement { border-top: 0; } td { - border-color: var(--mdc-theme-surface); + border-color: var(--md-sys-color-surface); font-family: monospace; font-size: 10px; } @@ -550,14 +550,14 @@ export class MatchesTableUi extends LitElement { } tr { - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); } .matchRow:hover { - background: var(--mdc-theme-surface); + background: var(--md-sys-color-surface); cursor: pointer; } .matchRowSelected { - background: var(--mdc-theme-surface); + background: var(--md-sys-color-surface); cursor: pointer; } .hiddenRow { @@ -570,7 +570,7 @@ export class MatchesTableUi extends LitElement { } .missing { - background: var(--mdc-theme-surface); + background: var(--md-sys-color-surface); } `; } diff --git a/src/matches_ui.ts b/src/matches_ui.ts index 05aa2a2..617275e 100644 --- a/src/matches_ui.ts +++ b/src/matches_ui.ts @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-button'; -import '@material/mwc-icon'; +import '@material/web/button/filled-button'; +import '@material/web/icon/icon'; import './batch_name_ui'; import './match_image_ui'; import './matches_table_ui'; @@ -52,12 +52,12 @@ export class MatchesUi extends LitElement {
- ${ + ${ this.referenceSelection === undefined || this.batchSelection.batch.index === this.referenceSelection.batch.index ? 'photo_library' : - 'join_inner'} + 'join_inner'} ${this.batchSelection.matchedDataPoints.rows.length}

@@ -90,13 +90,12 @@ export class MatchesUi extends LitElement { ${rdModeHash === undefined ? html`` : html` - - open_in_new - + Rate-Distortion + show_chart + open_in_new + `}

`; } @@ -138,8 +137,8 @@ export class MatchesUi extends LitElement { padding: 0 15px; height: 40px; border-radius: 30px; - background: var(--mdc-theme-primary); - color: var(--mdc-theme-background); + background: var(--md-sys-color-primary); + color: var(--md-sys-color-background); display: flex; align-items: center; gap: 5px; @@ -150,7 +149,7 @@ export class MatchesUi extends LitElement { margin: 0; } - mwc-button mwc-icon { + md-filled-button md-icon { margin-left: 8px; font-size: 16px; } diff --git a/src/metric_test.ts b/src/metric_test.ts index f98dc9b..a16e344 100644 --- a/src/metric_test.ts +++ b/src/metric_test.ts @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'jasmine'; - import {Batch, Field} from './entry'; import {Match} from './matcher'; import {computeStats, FieldMetric} from './metric'; diff --git a/src/metric_ui.ts b/src/metric_ui.ts index 317c55a..df9fdb9 100644 --- a/src/metric_ui.ts +++ b/src/metric_ui.ts @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-icon'; -import './mwc_button_fit'; +import '@material/web/icon/icon'; import './tooltip_ui'; import {css, html, LitElement} from 'lit'; @@ -33,24 +32,23 @@ export class MetricUi extends LitElement { private renderDeleteButton() { if (this.isFirst && this.isLast) { - // title on a disabled mwc-button-fit does not work. Encapsulate in a div. + // title on a disabled button does not work. Encapsulate in a div. return html`
- delete + + delete +
`; } - return html` { + return html` + { this.metric.enabled = false; dispatch(EventType.MATCHER_OR_METRIC_CHANGED); }} - title="Delete metric" - >delete`; + title="Delete metric"> + delete + `; } override render() { @@ -71,7 +69,7 @@ export class MetricUi extends LitElement { static override styles = css` :host { - background-color: var(--mdc-theme-surface); + background-color: var(--md-sys-color-surface); margin: 0; padding: 6px; border-radius: 6px; @@ -82,12 +80,14 @@ export class MetricUi extends LitElement { } p { margin: 0; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); font-size: 20px; } - mwc-icon { - font-size: 20px; + md-filled-icon-button { + --md-filled-icon-button-icon-size: 20px; + --md-filled-icon-button-container-width: 24px; + --md-filled-icon-button-container-height: 24px; } `; } diff --git a/src/metrics_ui.ts b/src/metrics_ui.ts index d4dd023..f36c41e 100644 --- a/src/metrics_ui.ts +++ b/src/metrics_ui.ts @@ -12,12 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-fab'; -import '@material/mwc-menu'; +import '@material/web/fab/fab'; +import '@material/web/menu/menu'; +import '@material/web/menu/menu-item'; +import '@material/web/icon/icon'; import './metric_ui'; -import {Fab} from '@material/mwc-fab'; -import {Menu} from '@material/mwc-menu'; +import {MdFab} from '@material/web/fab/fab'; +import {MdMenu} from '@material/web/menu/menu'; +import {MenuItem} from '@material/web/menu/menu-item'; import {css, html, LitElement} from 'lit'; import {customElement, property, query} from 'lit/decorators.js'; @@ -30,8 +33,8 @@ import {State} from './state'; export class MetricsUi extends LitElement { @property({attribute: false}) state!: State; - @query('#addMetricMenu') private readonly addMetricMenu!: Menu; - @query('#addMetricButton') private readonly addMetricButton!: Fab; + @query('#addMetricMenu') private readonly addMetricMenu!: MdMenu; + @query('#addMetricButton') private readonly addMetricButton!: MdFab; override connectedCallback() { super.connectedCallback(); @@ -44,35 +47,32 @@ export class MetricsUi extends LitElement { return html`${this.state.metrics.map((metric: FieldMetric) => { const fieldName = this.state.batches[0].fields[metric.fieldIndices[0]].displayName; - return metric.enabled ? - html`${fieldName}` : - html`${fieldName}`; + return metric.enabled ? html` + ${fieldName}` : + html` { + metric.enabled = true; + dispatch(EventType.MATCHER_OR_METRIC_CHANGED); + }}>${fieldName}`; })}`; } private renderAddMetricMenu() { - // mwc-menu and its anchor need a parent with position set to relative. + // md-menu and its anchor need a parent with position set to relative. return html` - { - this.addMetricMenu.show(); + this.addMetricMenu.open = !this.addMetricMenu.open; }} - id="addMetricButton"> - { - this.state.metrics[e.detail.index].enabled = true; - dispatch(EventType.MATCHER_OR_METRIC_CHANGED); - }}> + id="addMetricButton"> + add + + ${this.renderAddMetricMenuItems()} - + `; } @@ -106,7 +106,7 @@ export class MetricsUi extends LitElement { static override styles = css` :host { - background: var(--mdc-theme-background); + background: var(--md-sys-color-background); padding: 6px; box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.2); border-radius: 16px; @@ -120,13 +120,17 @@ export class MetricsUi extends LitElement { align-self: flex-end; margin-left: auto; } - .menuItemDisabled { - color: grey; - } #addMetricButton { - /* Save screen space. */ - margin: -6px; + --md-fab-container-width: 32px; + --md-fab-container-height: 32px; + --md-fab-icon-size: 20px; + } + + md-menu-item { + --md-menu-item-one-line-container-height: 20px; + --md-menu-item-top-space: 0; + --md-menu-item-bottom-space: 0; } `; } diff --git a/src/mwc_button_fit.ts b/src/mwc_button_fit.ts deleted file mode 100644 index 8e008bf..0000000 --- a/src/mwc_button_fit.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -import {Button} from '@material/mwc-button'; -import {customElement} from 'lit/decorators.js'; - -/** Same as but with custom width and height. */ -@customElement('mwc-button-fit') -export class MwcButtonFit extends Button { - protected override firstUpdated() { - const button = this.shadowRoot!.querySelector('button')!; - button.style.minWidth = '0'; - button.style.height = 'auto'; - button.style.padding = '2px 4px'; - } -} \ No newline at end of file diff --git a/src/panel_ui.ts b/src/panel_ui.ts index 7bae1da..90e7f20 100644 --- a/src/panel_ui.ts +++ b/src/panel_ui.ts @@ -12,18 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-button'; -import '@material/mwc-fab'; -import '@material/mwc-menu'; -import '@material/mwc-tab-bar'; -import '@material/mwc-tab'; +import '@material/web/button/filled-button'; +import '@material/web/fab/fab'; +import '@material/web/menu/menu'; +import '@material/web/menu/menu-item'; +import '@material/web/tabs/tabs'; +import '@material/web/tabs/secondary-tab'; import './batch_name_ui'; import './batch_selection_ui'; import './batch_ui'; import './matches_ui'; +import '@material/web/icon/icon'; -import {ActionDetail} from '@material/mwc-list'; -import {Menu} from '@material/mwc-menu'; +import {MdMenu} from '@material/web/menu/menu'; +import {MenuItem} from '@material/web/menu/menu-item'; import {css, html, LitElement} from 'lit'; import {customElement, property, query} from 'lit/decorators.js'; @@ -43,7 +45,7 @@ export class PanelUi extends LitElement { /** Currently displayed component. */ private currentTab = BatchTab.METADATA; - @query('#selectionMenu') private readonly selectionMenu!: Menu; + @query('#selectionMenu') private readonly selectionMenu!: MdMenu; override connectedCallback() { super.connectedCallback(); @@ -111,34 +113,32 @@ export class PanelUi extends LitElement { }}>

- { - this.selectionMenu.show(); + this.selectionMenu.open = !this.selectionMenu.open; }}> - - ) => { - this.batch = this.state.batches[e.detail.index]; - this.requestUpdate(); - }}> + arrow_drop_down + + ${ this.state.batches.map( (otherBatch) => html` - + { + this.batch = otherBatch; + this.requestUpdate(); + }}> ${ (!this.state.rdMode && otherBatch.index === this.state.referenceBatchSelectionIndex) ? html`reference` : html``} - `)} - + `)} +

${ @@ -146,46 +146,46 @@ export class PanelUi extends LitElement { // Rate-Distortion curve mode does not use any batch as reference. '' : batchIndex === this.state.referenceBatchSelectionIndex ? - // disabled mwc-button title does not appear. Use a div. + // disabled md-filled-button title does not appear. Use a div. html`
- - + Set as reference +
` : html` - - + Set as reference + `}
- ) => { - if (event.detail.index === BatchTab.METADATA) { + { + const activeTabIndex = (event.target as any).activeTabIndex; + if (activeTabIndex === BatchTab.METADATA) { dispatch(EventType.BATCH_INFO_REQUEST, {batchIndex}); - } else if (event.detail.index === BatchTab.FILTERS_AND_ROWS) { + } else if (activeTabIndex === BatchTab.FILTERS_AND_ROWS) { dispatch(EventType.FILTERED_DATA_INFO_REQUEST, {batchIndex}); - } else if (event.detail.index === BatchTab.MATCHES) { + } else if (activeTabIndex === BatchTab.MATCHES) { dispatch(EventType.MATCHES_INFO_REQUEST, {batchIndex}); } }}> - - - - - - + Metadata + info + + Filters and rows + filter_alt + + ${showRowsOnly ? 'Rows' : 'Matches'} + ${ + showRowsOnly ? 'photo_library' : 'join_inner'} + + @@ -202,8 +202,9 @@ export class PanelUi extends LitElement { style=${activeIndex === BatchTab.MATCHES ? '' : 'display: none'}> - - + + close +
`; } @@ -225,7 +226,7 @@ export class PanelUi extends LitElement { } #dialog { - background-color: var(--mdc-theme-surface); + background-color: var(--md-sys-color-surface); position: absolute; left: 40px; top: 40px; @@ -241,8 +242,8 @@ export class PanelUi extends LitElement { overflow: hidden; } - mwc-tab-bar { - background: var(--mdc-theme-surface); + md-tabs { + background: var(--md-sys-color-surface); } #closeButton { @@ -259,27 +260,30 @@ export class PanelUi extends LitElement { gap: 10px; } h1 { - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); } #selectionButton { margin: 0; pointer-events: auto; - --mdc-theme-primary: white; - --mdc-theme-on-primary: var(--mdc-theme-text); + --md-sys-color-primary: var(--md-sys-color-background); + --md-sys-color-on-primary: var(--md-sys-color-text); position: relative; } #selectionButton batch-name-ui { - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); font-size: 20px; white-space: nowrap; text-transform: none; } #selectionMenu { - --mdc-menu-item-height: 20px; + --md-menu-item-one-line-container-height: 20px; + --md-menu-item-top-space: 0; + --md-menu-item-bottom-space: 0; + white-space: nowrap; } .referenceBatchChip { - background: var(--mdc-theme-primary); - color: var(--mdc-theme-background); + background: var(--md-sys-color-secondary); + color: var(--md-sys-color-background); border-radius: 16px; padding: 2px 8px; font-size: 12px; diff --git a/src/plot_overlay_ui.ts b/src/plot_overlay_ui.ts index b70c4fc..362fd43 100644 --- a/src/plot_overlay_ui.ts +++ b/src/plot_overlay_ui.ts @@ -12,16 +12,18 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-button'; -import '@material/mwc-menu'; +import '@material/web/button/filled-button'; +import '@material/web/menu/menu'; +import '@material/web/menu/menu-item'; +import '@material/web/icon/icon'; -import {Button} from '@material/mwc-button'; -import {ActionDetail} from '@material/mwc-list'; -import {Menu} from '@material/mwc-menu'; +import {MdFilledButton} from '@material/web/button/filled-button'; +import {MdMenu} from '@material/web/menu/menu'; +import {MenuItem} from '@material/web/menu/menu-item'; import {css, html, LitElement} from 'lit'; import {customElement, property, query} from 'lit/decorators.js'; -import {FieldId, DISTORTION_METRIC_FIELD_IDS} from './entry'; +import {DISTORTION_METRIC_FIELD_IDS, FieldId} from './entry'; import {dispatch, EventType} from './events'; import {FieldMetric} from './metric'; import {State} from './state'; @@ -38,7 +40,8 @@ function fieldIdToString(id: FieldId) { if (id === FieldId.FLIP) return 'better looking'; if (id === FieldId.LPIPS) return 'better looking'; if (id === FieldId.P3NORM) return 'better looking'; - if (DISTORTION_METRIC_FIELD_IDS.includes(id)) return null; // Should not happen. + if (DISTORTION_METRIC_FIELD_IDS.includes(id)) + return null; // Should not happen. if (id === FieldId.ENCODED_SIZE) return 'smaller file'; if (id === FieldId.ENCODING_DURATION) return 'faster encoding'; if (id === FieldId.DECODING_DURATION) return 'faster decoding'; @@ -51,10 +54,11 @@ function fieldIdToString(id: FieldId) { export class PlotOverlayUi extends LitElement { @property({attribute: false}) state: State|undefined = undefined; - @query('#verticalMenu') private readonly verticalMenu!: Menu; - @query('#verticalButton') private readonly verticalButton!: Button; - @query('#horizontalMenu') private readonly horizontalMenu!: Menu; - @query('#horizontalButton') private readonly horizontalButton!: Button; + @query('#verticalMenu') private readonly verticalMenu!: MdMenu; + @query('#verticalButton') private readonly verticalButton!: MdFilledButton; + @query('#horizontalMenu') private readonly horizontalMenu!: MdMenu; + @query('#horizontalButton') + private readonly horizontalButton!: MdFilledButton; override render() { let verticalFieldIndex = -1; @@ -77,12 +81,10 @@ export class PlotOverlayUi extends LitElement { horizontalTitle = `${field.displayName} (click to change)`; } - const fieldIndices: number[] = []; const enabledMetrics: FieldMetric[] = []; if (this.state !== undefined) { for (const metric of this.state.metrics) { if (!metric.enabled) continue; - fieldIndices.push(metric.fieldIndices[0]); enabledMetrics.push(metric); } } @@ -90,50 +92,65 @@ export class PlotOverlayUi extends LitElement { return html`
- { - this.verticalMenu.show(); + this.verticalMenu.open = !this.verticalMenu.open; }}> + arrow_forward ${verticalString} - - ) => { - this.state!.plotMetricVertical = enabledMetrics[e.detail.index]; - dispatch(EventType.MATCHER_OR_METRIC_CHANGED); - }}> - ${fieldIndices.map((fieldIndex) => html` - - ${this.state!.batches[0].fields[fieldIndex].displayName} - `)} - + + + ${ + enabledMetrics.map( + (metric) => html` + { + this.state!.plotMetricVertical = metric; + console.log(this.state!.plotMetricVertical); + dispatch(EventType.MATCHER_OR_METRIC_CHANGED); + }}> + ${ + this.state!.batches[0] + .fields[metric.fieldIndices[0]] + .displayName} + `)} +
- { - this.horizontalMenu.show(); + this.horizontalMenu.open = !this.horizontalMenu.open; }}> + arrow_back ${horizontalString} - - ) => { - this.state!.plotMetricHorizontal = enabledMetrics[e.detail.index]; - dispatch(EventType.MATCHER_OR_METRIC_CHANGED); - }}> - ${fieldIndices.map((fieldIndex) => html` - - ${this.state!.batches[0].fields[fieldIndex].displayName} - `)} - + + + ${ + enabledMetrics.map( + (metric) => html` + { + this.state!.plotMetricHorizontal = metric; + dispatch(EventType.MATCHER_OR_METRIC_CHANGED); + }}> + ${ + this.state!.batches[0] + .fields[metric.fieldIndices[0]] + .displayName} + `)} +
`; } @@ -174,7 +191,8 @@ export class PlotOverlayUi extends LitElement { #horizontalButton { margin: 0; pointer-events: auto; - --mdc-theme-primary: black; + --md-sys-color-primary: white; + --md-sys-color-on-primary: black; position: relative; } #verticalButton span, diff --git a/src/sentence_ui.ts b/src/sentence_ui.ts index 0b67942..30ae8d5 100644 --- a/src/sentence_ui.ts +++ b/src/sentence_ui.ts @@ -294,7 +294,7 @@ export class SentenceUi extends LitElement { } p { margin: 10px 0; - color: var(--mdc-theme-text); + color: var(--md-sys-color-text); font-size: 20px; } batch-name-ui:hover { diff --git a/src/settings_ui.ts b/src/settings_ui.ts index 6f2f542..938c748 100644 --- a/src/settings_ui.ts +++ b/src/settings_ui.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-switch'; +import '@material/web/switch/switch'; import './filtered_images_ui'; import './filters_ui'; @@ -42,13 +42,13 @@ export class SettingsUi extends LitElement { Linear x axis - { this.state.horizontalLogScale = !this.state.horizontalLogScale; dispatch(EventType.MATCHER_OR_METRIC_CHANGED); dispatch(EventType.SETTINGS_CHANGED); }}> - + Logarithmic x axis @@ -57,13 +57,13 @@ export class SettingsUi extends LitElement { Linear y axis - { this.state.verticalLogScale = !this.state.verticalLogScale; dispatch(EventType.MATCHER_OR_METRIC_CHANGED); dispatch(EventType.SETTINGS_CHANGED); }}> - + Logarithmic y axis @@ -72,13 +72,13 @@ export class SettingsUi extends LitElement { Hide data points - { this.state.showEachPoint = !this.state.showEachPoint; dispatch(EventType.MATCHER_OR_METRIC_CHANGED); dispatch(EventType.SETTINGS_CHANGED); }}> - + Show data points @@ -88,13 +88,13 @@ export class SettingsUi extends LitElement { Match set - { this.state.matchRepeatedly = !this.state.matchRepeatedly; dispatch(EventType.MATCHER_OR_METRIC_CHANGED); dispatch(EventType.SETTINGS_CHANGED); }}> - + Match multiset @@ -103,13 +103,13 @@ export class SettingsUi extends LitElement { Absolute metrics - { this.state.showRelativeRatios = !this.state.showRelativeRatios; dispatch(EventType.MATCHER_OR_METRIC_CHANGED); dispatch(EventType.SETTINGS_CHANGED); }}> - + Relative ratios @@ -118,7 +118,7 @@ export class SettingsUi extends LitElement { Arithmetic mean - { @@ -126,7 +126,7 @@ export class SettingsUi extends LitElement { dispatch(EventType.MATCHER_OR_METRIC_CHANGED); dispatch(EventType.SETTINGS_CHANGED); }}> - + Geometric mean @@ -135,7 +135,7 @@ export class SettingsUi extends LitElement { Hide X error bars - - + Show X error bars @@ -156,7 +156,7 @@ export class SettingsUi extends LitElement { Hide Y error bars - - + Show Y error bars @@ -177,12 +177,12 @@ export class SettingsUi extends LitElement { Show some rows - { this.state.showAllRows = !this.state.showAllRows; dispatch(EventType.SETTINGS_CHANGED); }}> - + Show all rows @@ -202,5 +202,19 @@ export class SettingsUi extends LitElement { display: flex; gap: 20px; } + + md-switch { + --md-switch-selected-handle-color: var(--md-sys-color-primary); + --md-switch-selected-track-color: var(--md-sys-color-surface); + --md-switch-selected-focus-track-color: var(--md-sys-color-background); + --md-switch-selected-hover-track-color: var(--md-sys-color-background); + --md-switch-touch-target-size: 24px; + --md-switch-track-height: 14px; + --md-switch-track-width: 36px; + --md-switch-handle-height: 8px; + --md-switch-handle-width: 8px; + --md-switch-selected-handle-height: 10px; + --md-switch-selected-handle-width: 10px; + } `; } diff --git a/src/state_hash_test.ts b/src/state_hash_test.ts index 931fe39..70ee2f9 100644 --- a/src/state_hash_test.ts +++ b/src/state_hash_test.ts @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'jasmine'; - import {Batch, Field} from './entry'; import {FieldFilterRangeFloat, FieldFilterStringSet} from './filter'; import {State} from './state'; diff --git a/src/state_test.ts b/src/state_test.ts index b9cb1e2..cf4cc78 100644 --- a/src/state_test.ts +++ b/src/state_test.ts @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -import 'jasmine'; - import {Batch, Field} from './entry'; import {dispatch, EventType} from './events'; import {State} from './state'; diff --git a/src/tooltip_ui.ts b/src/tooltip_ui.ts index 2b94f86..f539279 100644 --- a/src/tooltip_ui.ts +++ b/src/tooltip_ui.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import '@material/mwc-icon'; +import '@material/web/icon/icon'; import {css, html, LitElement} from 'lit'; import {customElement, property} from 'lit/decorators.js'; @@ -27,7 +27,7 @@ export class TooltipUi extends LitElement { override render() { return html` - ${this.icon} + ${this.icon}

${this.text}

`; } @@ -36,8 +36,8 @@ export class TooltipUi extends LitElement { position: relative; /* For "position: absolute;" below to work. */ } - mwc-icon { - color: var(--mdc-theme-primary); + md-icon { + color: var(--md-sys-color-primary); font-size: 24px; vertical-align: middle; } @@ -51,8 +51,8 @@ export class TooltipUi extends LitElement { padding: 6px; border-radius: 6px; box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 6px 0px; - background-color: var(--mdc-theme-background); - color: var(--mdc-theme-text); + background-color: var(--md-sys-color-background); + color: var(--md-sys-color-text); font-size: 12px; text-align: justify; @@ -60,7 +60,7 @@ export class TooltipUi extends LitElement { display: none; } - mwc-icon:hover~p, p:hover { + md-icon:hover~p, p:hover { display: block; } `; diff --git a/web-test-runner.config.mjs b/web-test-runner.config.mjs new file mode 100644 index 0000000..3e31775 --- /dev/null +++ b/web-test-runner.config.mjs @@ -0,0 +1,28 @@ +/** + * @license + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { esbuildPlugin } from '@web/dev-server-esbuild'; +import { jasmineTestRunnerConfig } from 'web-test-runner-jasmine'; + +export default { + ...jasmineTestRunnerConfig(), + nodeResolve: true, + files: ['src/**/*_test.ts'], + plugins: [ + esbuildPlugin({ ts: true, tsconfig: './tsconfig.json' }), + ], +};