From f4152a5474b661d72b69e7a8cab41639ec7fb8c0 Mon Sep 17 00:00:00 2001 From: Westbrook Johnson Date: Mon, 6 Feb 2023 09:40:11 -0500 Subject: [PATCH] fix: prepare for querying child items while disconnected --- packages/menu/src/MenuItem.ts | 4 +- .../stories/menu-item.disconnected.stories.ts | 189 ++++++++++++++++++ 2 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 packages/menu/stories/menu-item.disconnected.stories.ts diff --git a/packages/menu/src/MenuItem.ts b/packages/menu/src/MenuItem.ts index 5b465e359f..4ef7553350 100644 --- a/packages/menu/src/MenuItem.ts +++ b/packages/menu/src/MenuItem.ts @@ -180,7 +180,7 @@ export class MenuItem extends LikeAnchor(Focusable) { return this._itemChildren; } - const iconSlot = this.shadowRoot.querySelector( + const iconSlot = this.shadowRoot?.querySelector( 'slot[name="icon"]' ) as HTMLSlotElement; const icon = !iconSlot @@ -191,7 +191,7 @@ export class MenuItem extends LikeAnchor(Focusable) { newElement.classList.toggle('icon'); return newElement; }); - const contentSlot = this.shadowRoot.querySelector( + const contentSlot = this.shadowRoot?.querySelector( 'slot:not([name])' ) as HTMLSlotElement; const content = !contentSlot diff --git a/packages/menu/stories/menu-item.disconnected.stories.ts b/packages/menu/stories/menu-item.disconnected.stories.ts new file mode 100644 index 0000000000..f12c1ba968 --- /dev/null +++ b/packages/menu/stories/menu-item.disconnected.stories.ts @@ -0,0 +1,189 @@ +/* +Copyright 2023 Adobe. All rights reserved. +This file is licensed to you 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 REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. +*/ + +import { html, LitElement, TemplateResult } from 'lit'; +import { property, state } from 'lit/decorators.js'; +import { repeat } from 'lit/directives/repeat.js'; +import { when } from 'lit/directives/when.js'; + +import '@spectrum-web-components/picker/sp-picker.js'; +import '@spectrum-web-components/button/sp-button.js'; +import { SpectrumMixin } from '@spectrum-web-components/base'; + +enum BlendModeValue { + normal = 2, + multiply = 3, + screen = 7, +} + +interface BlendModeOption { + value: BlendModeValue; + title: string; + subtitle: string; + thumbnail: string; +} + +const XElement = SpectrumMixin(LitElement); + +class MyContainer extends XElement { + @state() + private _counter = 0; + + private _handleClick(): void { + this._counter += 1; + } + + protected override render(): TemplateResult { + return html` +
+ ${when( + this._counter % 2 === 0, + () => html` + + `, + () => html` + + ` + )} + + Switch views + +
+ `; + } +} + +customElements.define('my-container', MyContainer); + +class MyView1 extends XElement { + protected override render(): TemplateResult { + const blendModeOptions = [ + { + value: BlendModeValue.normal, + title: 'Normal 1', + subtitle: 'No effect applied', + }, + { + value: BlendModeValue.multiply, + title: 'Multiply', + subtitle: 'Darken shadows with contrast and details', + }, + { + value: BlendModeValue.screen, + title: 'Screen', + subtitle: 'Brighten highlights with contrast and details', + }, + ]; + return html` + View 1 + + `; + } +} + +customElements.define('my-view1', MyView1); + +class MyView2 extends XElement { + protected override render(): TemplateResult { + const blendModeOptions = [ + { + value: BlendModeValue.normal, + title: 'Normal 2', + subtitle: 'No effect applied', + }, + { + value: BlendModeValue.multiply, + title: 'Multiply', + subtitle: 'Darken shadows with contrast and details', + }, + { + value: BlendModeValue.screen, + title: 'Screen', + subtitle: 'Brighten highlights with contrast and details', + }, + ]; + return html` + View 2 + + `; + } +} + +customElements.define('my-view2', MyView2); + +class MyPicker extends XElement { + @property({ type: Array }) + public blendModeOptions: BlendModeOption[] = []; + + @property() + public blendMode: number = BlendModeValue.normal; + + private _renderBlendOptions(): TemplateResult { + return html` + ${repeat( + this.blendModeOptions, + // This is intentional so that repeat directive will add instead of + // update existing DOM which will then trigger error in + // MenuItem.childrenItem + // Using .value for the key will workaround the issue + (blendModeOption) => blendModeOption, + (blendModeOption: BlendModeOption) => + html` + + ${blendModeOption.title} + + ${blendModeOption.subtitle} + + + ` + )} + `; + } + protected override render(): TemplateResult { + return html` + + ${this._renderBlendOptions()} + + `; + } +} + +customElements.define('my-picker', MyPicker); + +export default { + component: 'sp-menu-item', + title: 'Menu Item/Disconnected', +}; + +export const disconnectedChildItems = (): TemplateResult => html` + +`; + +disconnectedChildItems.swc_vrt = { + skip: true, +};