From e3d78d6dc5d8af0b4d2cb860954b6a6262b9f67c Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 5 Jan 2022 12:49:05 -0800 Subject: [PATCH] Convert ha-gallery to TS (#11102) * Convert ha-gallery to TS * Prepare gallery to be design portal * Import card in introduction * Clean up demo IDs * Convert demo-cards * TypeScript conversion of demo-card * Fix default demo --- build-scripts/gulp/gallery.js | 2 +- gallery/src/components/demo-card.js | 129 ---------- gallery/src/components/demo-card.ts | 129 ++++++++++ gallery/src/components/demo-cards.js | 83 ------- gallery/src/components/demo-cards.ts | 92 +++++++ gallery/src/demos/demo-hui-iframe-card.ts | 12 +- ...r-rows.ts => demo-hui-media-player-row.ts} | 2 +- gallery/src/demos/demo-introduction.ts | 43 ++++ gallery/src/ha-gallery.js | 225 ------------------ gallery/src/ha-gallery.ts | 207 ++++++++++++++++ package.json | 2 + src/managers/notification-manager.ts | 4 + yarn.lock | 62 ++++- 13 files changed, 550 insertions(+), 442 deletions(-) delete mode 100644 gallery/src/components/demo-card.js create mode 100644 gallery/src/components/demo-card.ts delete mode 100644 gallery/src/components/demo-cards.js create mode 100644 gallery/src/components/demo-cards.ts rename gallery/src/demos/{demo-hui-media-player-rows.ts => demo-hui-media-player-row.ts} (97%) create mode 100644 gallery/src/demos/demo-introduction.ts delete mode 100644 gallery/src/ha-gallery.js create mode 100644 gallery/src/ha-gallery.ts diff --git a/build-scripts/gulp/gallery.js b/build-scripts/gulp/gallery.js index 2823ad70b1..9522d48b5c 100644 --- a/build-scripts/gulp/gallery.js +++ b/build-scripts/gulp/gallery.js @@ -25,7 +25,7 @@ gulp.task("gather-gallery-demos", async function gatherDemos() { for (const file of files) { const demoId = path.basename(file, ".ts"); const demoPath = "../src/demos/" + demoId; - content += ` "${demoId}": () => import("${demoPath}"),\n`; + content += ` "${demoId.substring(5)}": () => import("${demoPath}"),\n`; } content += "};"; diff --git a/gallery/src/components/demo-card.js b/gallery/src/components/demo-card.js deleted file mode 100644 index 4d9ce53899..0000000000 --- a/gallery/src/components/demo-card.js +++ /dev/null @@ -1,129 +0,0 @@ -import { html } from "@polymer/polymer/lib/utils/html-tag"; -/* eslint-plugin-disable lit */ -import { PolymerElement } from "@polymer/polymer/polymer-element"; -import { load } from "js-yaml"; -import { createCardElement } from "../../../src/panels/lovelace/create-element/create-card-element"; - -class DemoCard extends PolymerElement { - static get template() { - return html` - -

- [[config.heading]] - -

-
-
- -
- `; - } - - static get properties() { - return { - hass: { - type: Object, - observer: "_hassChanged", - }, - config: { - type: Object, - observer: "_configChanged", - }, - showConfig: Boolean, - _size: { - type: Number, - }, - }; - } - - ready() { - super.ready(); - } - - _configChanged(config) { - const card = this.$.card; - while (card.lastChild) { - card.removeChild(card.lastChild); - } - - const el = this._createCardElement(load(config.config)[0]); - card.appendChild(el); - this._getSize(el); - } - - async _getSize(el) { - await customElements.whenDefined(el.localName); - - if (!("getCardSize" in el)) { - this._size = undefined; - return; - } - this._size = await el.getCardSize(); - } - - _createCardElement(cardConfig) { - const element = createCardElement(cardConfig); - if (this.hass) { - element.hass = this.hass; - } - element.addEventListener( - "ll-rebuild", - (ev) => { - ev.stopPropagation(); - this._rebuildCard(element, cardConfig); - }, - { once: true } - ); - return element; - } - - _rebuildCard(cardElToReplace, config) { - const newCardEl = this._createCardElement(config); - cardElToReplace.parentElement.replaceChild(newCardEl, cardElToReplace); - } - - _hassChanged(hass) { - const card = this.$.card.lastChild; - if (card) card.hass = hass; - } - - _trim(config) { - return config.trim(); - } -} - -customElements.define("demo-card", DemoCard); diff --git a/gallery/src/components/demo-card.ts b/gallery/src/components/demo-card.ts new file mode 100644 index 0000000000..1c08792952 --- /dev/null +++ b/gallery/src/components/demo-card.ts @@ -0,0 +1,129 @@ +import { load } from "js-yaml"; +import { html, css, LitElement, PropertyValues } from "lit"; +import { customElement, property, query, state } from "lit/decorators"; +import { createCardElement } from "../../../src/panels/lovelace/create-element/create-card-element"; +import { HomeAssistant } from "../../../src/types"; + +export interface DemoCardConfig { + heading: string; + config: string; +} + +@customElement("demo-card") +class DemoCard extends LitElement { + @property() public hass!: HomeAssistant; + + @property() public config!: DemoCardConfig; + + @property() public showConfig = false; + + @state() private _size?: number; + + @query("#card") private _card!: HTMLElement; + + render() { + return html` +

+ ${this.config.heading} + ${this._size !== undefined + ? html`(size ${this._size})` + : ""} +

+
+
+ ${this.showConfig ? html`
${this.config.config.trim()}
` : ""} +
+ `; + } + + updated(changedProps: PropertyValues) { + super.updated(changedProps); + + if (changedProps.has("config")) { + const card = this._card; + while (card.lastChild) { + card.removeChild(card.lastChild); + } + + const el = this._createCardElement((load(this.config.config) as any)[0]); + card.appendChild(el); + this._getSize(el); + } + + if (changedProps.has("hass")) { + const card = this._card.lastChild; + if (card) { + (card as any).hass = this.hass; + } + } + } + + async _getSize(el) { + await customElements.whenDefined(el.localName); + + if (!("getCardSize" in el)) { + this._size = undefined; + return; + } + this._size = await el.getCardSize(); + } + + _createCardElement(cardConfig) { + const element = createCardElement(cardConfig); + if (this.hass) { + element.hass = this.hass; + } + element.addEventListener( + "ll-rebuild", + (ev) => { + ev.stopPropagation(); + this._rebuildCard(element, cardConfig); + }, + { once: true } + ); + return element; + } + + _rebuildCard(cardElToReplace, config) { + const newCardEl = this._createCardElement(config); + cardElToReplace.parentElement.replaceChild(newCardEl, cardElToReplace); + } + + static styles = css` + .root { + display: flex; + } + h2 { + margin: 0 0 20px; + color: var(--primary-color); + } + h2 small { + font-size: 0.5em; + color: var(--primary-text-color); + } + #card { + max-width: 400px; + width: 100vw; + } + pre { + width: 400px; + margin: 0 16px; + overflow: auto; + color: var(--primary-text-color); + } + @media only screen and (max-width: 800px) { + .root { + flex-direction: column; + } + pre { + margin: 16px 0; + } + } + `; +} + +declare global { + interface HTMLElementTagNameMap { + "demo-card": DemoCard; + } +} diff --git a/gallery/src/components/demo-cards.js b/gallery/src/components/demo-cards.js deleted file mode 100644 index 59faa671a6..0000000000 --- a/gallery/src/components/demo-cards.js +++ /dev/null @@ -1,83 +0,0 @@ -import "@polymer/app-layout/app-toolbar/app-toolbar"; -import { html } from "@polymer/polymer/lib/utils/html-tag"; -/* eslint-plugin-disable lit */ -import { PolymerElement } from "@polymer/polymer/polymer-element"; -import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element"; -import "../../../src/components/ha-formfield"; -import "../../../src/components/ha-switch"; -import "./demo-card"; - -class DemoCards extends PolymerElement { - static get template() { - return html` - - -
- - - - - - - -
-
-
-
- -
-
- `; - } - - static get properties() { - return { - configs: Object, - hass: Object, - _showConfig: { - type: Boolean, - value: false, - }, - }; - } - - _showConfigToggled(ev) { - this._showConfig = ev.target.checked; - } - - _darkThemeToggled(ev) { - applyThemesOnElement(this.$.container, { themes: {} }, "default", { - dark: ev.target.checked, - }); - } -} - -customElements.define("demo-cards", DemoCards); diff --git a/gallery/src/components/demo-cards.ts b/gallery/src/components/demo-cards.ts new file mode 100644 index 0000000000..609577e7f1 --- /dev/null +++ b/gallery/src/components/demo-cards.ts @@ -0,0 +1,92 @@ +import "@polymer/app-layout/app-toolbar/app-toolbar"; +import { html, css, LitElement } from "lit"; +import { customElement, property, query, state } from "lit/decorators"; +import { applyThemesOnElement } from "../../../src/common/dom/apply_themes_on_element"; +import "../../../src/components/ha-formfield"; +import "../../../src/components/ha-switch"; +import { HomeAssistant } from "../../../src/types"; +import "./demo-card"; +import type { DemoCardConfig } from "./demo-card"; + +@customElement("demo-cards") +class DemoCards extends LitElement { + @property() public configs!: DemoCardConfig[]; + + @property() public hass!: HomeAssistant; + + @state() private _showConfig = false; + + @query("#container") private _container!: HTMLElement; + + render() { + return html` + +
+ + + + + + + +
+
+
+
+ ${this.configs.map( + (config) => html` + + ` + )} +
+
+ `; + } + + _showConfigToggled(ev) { + this._showConfig = ev.target.checked; + } + + _darkThemeToggled(ev) { + applyThemesOnElement(this._container, { themes: {} } as any, "default", { + dark: ev.target.checked, + }); + } + + static styles = css` + #container { + min-height: calc(100vh - 128px); + background: var(--primary-background-color); + } + .cards { + display: flex; + flex-wrap: wrap; + justify-content: center; + } + demo-card { + margin: 16px 16px 32px; + } + app-toolbar { + background-color: var(--light-primary-color); + } + .filters { + margin-left: 60px; + } + ha-formfield { + margin-right: 16px; + } + `; +} + +declare global { + interface HTMLElementTagNameMap { + "demo-cards": DemoCards; + } +} diff --git a/gallery/src/demos/demo-hui-iframe-card.ts b/gallery/src/demos/demo-hui-iframe-card.ts index 811d858e44..32d7e39140 100644 --- a/gallery/src/demos/demo-hui-iframe-card.ts +++ b/gallery/src/demos/demo-hui-iframe-card.ts @@ -1,5 +1,6 @@ -import { html, LitElement, TemplateResult } from "lit"; -import { customElement } from "lit/decorators"; +import { html, LitElement, PropertyValues, TemplateResult } from "lit"; +import { customElement, query } from "lit/decorators"; +import { provideHass } from "../../../src/fake_data/provide_hass"; import "../components/demo-cards"; const CONFIGS = [ @@ -38,9 +39,16 @@ const CONFIGS = [ @customElement("demo-hui-iframe-card") class DemoIframe extends LitElement { + @query("demo-cards") private _demos!: HTMLElement; + protected render(): TemplateResult { return html``; } + + protected firstUpdated(changedProperties: PropertyValues) { + super.firstUpdated(changedProperties); + provideHass(this._demos); + } } declare global { diff --git a/gallery/src/demos/demo-hui-media-player-rows.ts b/gallery/src/demos/demo-hui-media-player-row.ts similarity index 97% rename from gallery/src/demos/demo-hui-media-player-rows.ts rename to gallery/src/demos/demo-hui-media-player-row.ts index 988d232e49..f99b20fcdf 100644 --- a/gallery/src/demos/demo-hui-media-player-rows.ts +++ b/gallery/src/demos/demo-hui-media-player-row.ts @@ -73,6 +73,6 @@ class DemoHuiMediaPlayerRow extends LitElement { declare global { interface HTMLElementTagNameMap { - "demo-hui-media-player-row": DemoHuiMediaPlayerRow; + "demo-hui-media-player-rows": DemoHuiMediaPlayerRow; } } diff --git a/gallery/src/demos/demo-introduction.ts b/gallery/src/demos/demo-introduction.ts new file mode 100644 index 0000000000..29e306bbff --- /dev/null +++ b/gallery/src/demos/demo-introduction.ts @@ -0,0 +1,43 @@ +import { css, html, LitElement, TemplateResult } from "lit"; +import { customElement } from "lit/decorators"; +import "../../../src/components/ha-card"; +import "../../../src/components/ha-markdown"; + +@customElement("demo-introduction") +export class DemoIntroduction extends LitElement { + protected render(): TemplateResult { + return html` + +
+ +
+
+ `; + } + + static get styles() { + return css` + ha-card { + max-width: 600px; + margin: 24px auto; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "demo-introduction": DemoIntroduction; + } +} diff --git a/gallery/src/ha-gallery.js b/gallery/src/ha-gallery.js deleted file mode 100644 index 671cbe9077..0000000000 --- a/gallery/src/ha-gallery.js +++ /dev/null @@ -1,225 +0,0 @@ -import "@polymer/app-layout/app-header-layout/app-header-layout"; -import "@polymer/app-layout/app-header/app-header"; -import "@polymer/app-layout/app-toolbar/app-toolbar"; -import "@polymer/paper-item/paper-item"; -import "@polymer/paper-item/paper-item-body"; -import { html } from "@polymer/polymer/lib/utils/html-tag"; -/* eslint-plugin-disable lit */ -import { PolymerElement } from "@polymer/polymer/polymer-element"; -import "../../src/components/ha-card"; -import "../../src/components/ha-icon"; -import "../../src/components/ha-icon-button"; -import "../../src/managers/notification-manager"; -import "../../src/styles/polymer-ha-style"; -// eslint-disable-next-line import/extensions -import { DEMOS } from "../build/import-demos"; - -class HaGallery extends PolymerElement { - static get template() { - return html` - - - - - - - - -
- [[_withDefault(_demo, "Home Assistant Gallery")]] -
-
-
- -
-
- -
-
- - `; - } - - static get properties() { - return { - _fakeHass: { - type: Object, - // Just enough for computeRTL - value: { - language: "en", - translationMetadata: { - translations: {}, - }, - }, - }, - _demo: { - type: String, - value: document.location.hash.substr(1), - observer: "_demoChanged", - }, - _demos: { - type: Array, - value: Object.keys(DEMOS), - }, - _lovelaceDemos: { - type: Array, - computed: "_computeLovelace(_demos)", - }, - _restDemos: { - type: Array, - computed: "_computeRest(_demos)", - }, - }; - } - - ready() { - super.ready(); - - this.addEventListener("show-notification", (ev) => - this.$.notifications.showDialog({ message: ev.detail.message }) - ); - - this.addEventListener("alert-dismissed-clicked", () => - this.$.notifications.showDialog({ message: "Alert dismissed clicked" }) - ); - this.addEventListener("hass-more-info", (ev) => { - if (ev.detail.entityId) { - this.$.notifications.showDialog({ - message: `Showing more info for ${ev.detail.entityId}`, - }); - } - }); - - window.addEventListener("hashchange", () => { - this._demo = document.location.hash.substr(1); - }); - } - - _withDefault(value, def) { - return value || def; - } - - _demoChanged(demo) { - const root = this.$.demo; - - while (root.lastChild) root.removeChild(root.lastChild); - - if (demo) { - DEMOS[demo](); - const el = document.createElement(demo); - root.appendChild(el); - } - } - - _computeHeaderButtonClass(demo) { - return demo ? "" : "invisible"; - } - - _backTapped() { - document.location.hash = ""; - } - - _computeLovelace(demos) { - return demos.filter((demo) => demo.includes("hui")); - } - - _computeRest(demos) { - return demos.filter((demo) => !demo.includes("hui")); - } -} - -customElements.define("ha-gallery", HaGallery); diff --git a/gallery/src/ha-gallery.ts b/gallery/src/ha-gallery.ts new file mode 100644 index 0000000000..d7d38b2381 --- /dev/null +++ b/gallery/src/ha-gallery.ts @@ -0,0 +1,207 @@ +import { mdiMenu } from "@mdi/js"; +import "@material/mwc-drawer"; +import "@material/mwc-top-app-bar-fixed"; +import { html, css, LitElement, PropertyValues } from "lit"; +import { customElement, property, query } from "lit/decorators"; +import "../../src/components/ha-icon-button"; +import "../../src/managers/notification-manager"; +import { haStyle } from "../../src/resources/styles"; +// eslint-disable-next-line import/extensions +import { DEMOS } from "../build/import-demos"; +import { dynamicElement } from "../../src/common/dom/dynamic-element-directive"; + +const DEMOS_GROUPED: { + header?: string; + demos?: string[]; + demoStart?: string; +}[] = [ + { + demos: ["introduction"], + }, + { + header: "Lovelace", + demoStart: "hui-", + }, + { + header: "Automation", + demoStart: "automation-", + }, + { + header: "Rest", + demoStart: "", + }, +]; + +const demosToProcess = new Set(Object.keys(DEMOS)); + +for (const group of Object.values(DEMOS_GROUPED)) { + if (group.demos) { + for (const demo of group.demos) { + demosToProcess.delete(demo); + } + } + if (!group.demos) { + group.demos = []; + } + if (group.demoStart !== undefined) { + for (const demo of demosToProcess) { + if (demo.startsWith(group.demoStart)) { + group.demos.push(demo); + demosToProcess.delete(demo); + } + } + } +} + +const FAKE_HASS = { + // Just enough for computeRTL for notification-manager + language: "en", + translationMetadata: { + translations: {}, + }, +}; + +@customElement("ha-gallery") +class HaGallery extends LitElement { + @property() private _demo = + document.location.hash.substring(1) || DEMOS_GROUPED[0].demos![0]; + + @query("notification-manager") + private _notifications!: HTMLElementTagNameMap["notification-manager"]; + + @query("mwc-drawer") + private _drawer!: HTMLElementTagNameMap["mwc-drawer"]; + + render() { + return html` + + Home Assistant Design + + +
+ + + +
${this._demo}
+
+
${dynamicElement(`demo-${this._demo}`)}
+
+
+ + `; + } + + private _renderDemo(demo: string, demoStart?: string) { + return html` + ${demoStart === undefined ? demo : demo.substring(demoStart.length)} + `; + } + + firstUpdated(changedProps: PropertyValues) { + super.firstUpdated(changedProps); + + this.addEventListener("show-notification", (ev) => + this._notifications.showDialog({ message: ev.detail.message }) + ); + + this.addEventListener("alert-dismissed-clicked", () => + this._notifications.showDialog({ message: "Alert dismissed clicked" }) + ); + this.addEventListener("hass-more-info", (ev) => { + if (ev.detail.entityId) { + this._notifications.showDialog({ + message: `Showing more info for ${ev.detail.entityId}`, + }); + } + }); + + document.location.hash = this._demo; + + window.addEventListener("hashchange", () => { + this._demo = document.location.hash.substring(1); + }); + } + + updated(changedProps: PropertyValues) { + super.updated(changedProps); + if (changedProps.has("_demo") && this._demo) { + DEMOS[this._demo](); + } + } + + _menuTapped() { + this._drawer.open = !this._drawer.open; + } + + static styles = [ + haStyle, + css` + :host { + -ms-user-select: initial; + -webkit-user-select: initial; + -moz-user-select: initial; + } + + .section { + font-weight: bold; + } + + .sidebar { + padding: 4px; + } + + .sidebar p { + margin: 1em 12px; + } + + .sidebar a { + color: var(--primary-text-color); + display: block; + padding: 4px 12px; + text-decoration: none; + position: relative; + } + + .sidebar a[active]::before { + border-radius: 4px; + position: absolute; + top: 0; + right: 2px; + bottom: 0; + left: 2px; + pointer-events: none; + content: ""; + transition: opacity 15ms linear; + will-change: opacity; + background-color: var(--sidebar-selected-icon-color); + opacity: 0.12; + } + `, + ]; +} + +declare global { + interface HTMLElementTagNameMap { + "ha-gallery": HaGallery; + } +} diff --git a/package.json b/package.json index 74a38b6ab1..0c0125cb79 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "@material/mwc-checkbox": "0.25.3", "@material/mwc-circular-progress": "0.25.3", "@material/mwc-dialog": "0.25.3", + "@material/mwc-drawer": "^0.25.3", "@material/mwc-fab": "0.25.3", "@material/mwc-formfield": "0.25.3", "@material/mwc-icon-button": "patch:@material/mwc-icon-button@0.25.3#./.yarn/patches/@material/mwc-icon-button/remove-icon.patch", @@ -66,6 +67,7 @@ "@material/mwc-tab": "0.25.3", "@material/mwc-tab-bar": "0.25.3", "@material/mwc-textfield": "0.25.3", + "@material/mwc-top-app-bar-fixed": "^0.25.3", "@material/top-app-bar": "14.0.0-canary.261f2db59.0", "@mdi/js": "6.5.95", "@mdi/svg": "6.5.95", diff --git a/src/managers/notification-manager.ts b/src/managers/notification-manager.ts index 7eb9b410cd..db71b05f32 100644 --- a/src/managers/notification-manager.ts +++ b/src/managers/notification-manager.ts @@ -92,6 +92,10 @@ class NotificationManager extends LitElement { customElements.define("notification-manager", NotificationManager); declare global { + interface HTMLElementTagNameMap { + "notification-manager": NotificationManager; + } + // for fire event interface HASSDomEvents { "hass-notification": ShowToastParams; diff --git a/yarn.lock b/yarn.lock index cf8e942bd8..285de20715 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2126,6 +2126,26 @@ __metadata: languageName: node linkType: hard +"@material/drawer@npm:=14.0.0-canary.261f2db59.0": + version: 14.0.0-canary.261f2db59.0 + resolution: "@material/drawer@npm:14.0.0-canary.261f2db59.0" + dependencies: + "@material/animation": 14.0.0-canary.261f2db59.0 + "@material/base": 14.0.0-canary.261f2db59.0 + "@material/dom": 14.0.0-canary.261f2db59.0 + "@material/elevation": 14.0.0-canary.261f2db59.0 + "@material/feature-targeting": 14.0.0-canary.261f2db59.0 + "@material/list": 14.0.0-canary.261f2db59.0 + "@material/ripple": 14.0.0-canary.261f2db59.0 + "@material/rtl": 14.0.0-canary.261f2db59.0 + "@material/shape": 14.0.0-canary.261f2db59.0 + "@material/theme": 14.0.0-canary.261f2db59.0 + "@material/typography": 14.0.0-canary.261f2db59.0 + tslib: ^2.1.0 + checksum: 92146c61e00220f7aab80e3631c752e11147bee22e4a09e7bac21d233ae0aeff9545efe4d4a0fb10e889161ba06433ce9222bdcfda73de3ea54027cdadb3571a + languageName: node + linkType: hard + "@material/elevation@npm:14.0.0-canary.261f2db59.0": version: 14.0.0-canary.261f2db59.0 resolution: "@material/elevation@npm:14.0.0-canary.261f2db59.0" @@ -2343,6 +2363,20 @@ __metadata: languageName: node linkType: hard +"@material/mwc-drawer@npm:^0.25.3": + version: 0.25.3 + resolution: "@material/mwc-drawer@npm:0.25.3" + dependencies: + "@material/drawer": =14.0.0-canary.261f2db59.0 + "@material/mwc-base": ^0.25.3 + blocking-elements: ^0.1.0 + lit: ^2.0.0 + tslib: ^2.0.1 + wicg-inert: ^3.0.0 + checksum: 1195301cd943c1f7dae92ef33c383f5a2c3238d26fa44dd006d3c90d1c101cf17a5e67e491ef6ec49889a5cef682ea2f410397ac76be556cde1c8cb79f06874d + languageName: node + linkType: hard + "@material/mwc-fab@npm:0.25.3": version: 0.25.3 resolution: "@material/mwc-fab@npm:0.25.3" @@ -2624,6 +2658,30 @@ __metadata: languageName: node linkType: hard +"@material/mwc-top-app-bar-fixed@npm:^0.25.3": + version: 0.25.3 + resolution: "@material/mwc-top-app-bar-fixed@npm:0.25.3" + dependencies: + "@material/mwc-top-app-bar": ^0.25.3 + "@material/top-app-bar": =14.0.0-canary.261f2db59.0 + lit: ^2.0.0 + tslib: ^2.0.1 + checksum: f142b0625b0b5bd9335b43db977a20502da49707415c69bb8df8ba3626f81cc4c8283aeeece6f20d3a401f370b33ac88a41ebdcaa04fe90d5b2067142b1c460c + languageName: node + linkType: hard + +"@material/mwc-top-app-bar@npm:^0.25.3": + version: 0.25.3 + resolution: "@material/mwc-top-app-bar@npm:0.25.3" + dependencies: + "@material/mwc-base": ^0.25.3 + "@material/top-app-bar": =14.0.0-canary.261f2db59.0 + lit: ^2.0.0 + tslib: ^2.0.1 + checksum: c71ad8f557232827bab4b0cdf69fc3aa8caa9aa84193a9b085d3504c7d5c7a8d1e17aab7ebcf84cd0983e2ada8c88cc28de3f1d3a824c0b4fb9ce2ba96b48912 + languageName: node + linkType: hard + "@material/notched-outline@npm:14.0.0-canary.261f2db59.0, @material/notched-outline@npm:=14.0.0-canary.261f2db59.0": version: 14.0.0-canary.261f2db59.0 resolution: "@material/notched-outline@npm:14.0.0-canary.261f2db59.0" @@ -2869,7 +2927,7 @@ __metadata: languageName: node linkType: hard -"@material/top-app-bar@npm:14.0.0-canary.261f2db59.0": +"@material/top-app-bar@npm:14.0.0-canary.261f2db59.0, @material/top-app-bar@npm:=14.0.0-canary.261f2db59.0": version: 14.0.0-canary.261f2db59.0 resolution: "@material/top-app-bar@npm:14.0.0-canary.261f2db59.0" dependencies: @@ -9022,6 +9080,7 @@ fsevents@^1.2.7: "@material/mwc-checkbox": 0.25.3 "@material/mwc-circular-progress": 0.25.3 "@material/mwc-dialog": 0.25.3 + "@material/mwc-drawer": ^0.25.3 "@material/mwc-fab": 0.25.3 "@material/mwc-formfield": 0.25.3 "@material/mwc-icon-button": "patch:@material/mwc-icon-button@0.25.3#./.yarn/patches/@material/mwc-icon-button/remove-icon.patch" @@ -9036,6 +9095,7 @@ fsevents@^1.2.7: "@material/mwc-tab": 0.25.3 "@material/mwc-tab-bar": 0.25.3 "@material/mwc-textfield": 0.25.3 + "@material/mwc-top-app-bar-fixed": ^0.25.3 "@material/top-app-bar": 14.0.0-canary.261f2db59.0 "@mdi/js": 6.5.95 "@mdi/svg": 6.5.95