From b06c3494c1c88413cb3d5e9dc7ff560b14c47744 Mon Sep 17 00:00:00 2001 From: Nayden Naydenov <31909318+nnaydenow@users.noreply.github.com> Date: Tue, 2 Apr 2024 17:08:15 +0300 Subject: [PATCH] framework: enable popover API (#8192) --- .../05-testing-UI5-Web-Components.md | 30 +- .../06-deep-dive-and-best-practices.md | 316 ------- .../07-typescript-in-UI5-Web-Components.md | 5 +- packages/base/bundle.esm.js | 1 - packages/base/config/wdio.conf.cjs | 8 - packages/base/src/StaticAreaItem.ts | 115 --- packages/base/src/UI5Element.ts | 74 +- packages/base/src/decorators/customElement.ts | 4 +- packages/base/src/features/OpenUI5Support.ts | 36 +- packages/base/src/renderer/LitRenderer.ts | 4 +- .../base/src/theming/getConstructableStyle.ts | 6 +- .../base/src/theming/getEffectiveStyle.ts | 16 +- packages/base/src/updateShadowRoot.ts | 16 +- packages/base/src/util/PopupUtils.ts | 25 - packages/base/test/elements/WithStaticArea.js | 77 -- .../base/test/specs/SystemDOMElements.spec.js | 75 +- packages/fiori/src/BarcodeScannerDialog.ts | 26 +- packages/fiori/src/MediaGallery.ts | 1 - .../fiori/src/NotificationListGroupItem.hbs | 2 + .../fiori/src/NotificationListGroupItem.ts | 6 +- packages/fiori/src/NotificationListItem.hbs | 2 + packages/fiori/src/NotificationListItem.ts | 6 +- .../fiori/src/NotificationListItemBase.ts | 24 +- packages/fiori/src/ShellBar.hbs | 2 + packages/fiori/src/ShellBar.ts | 52 +- packages/fiori/src/SideNavigation.hbs | 2 + packages/fiori/src/SideNavigation.ts | 60 +- packages/fiori/src/SideNavigationPopover.hbs | 2 + packages/fiori/src/Wizard.hbs | 2 + packages/fiori/src/Wizard.ts | 19 +- packages/fiori/src/WizardPopover.hbs | 1 - packages/fiori/test/specs/ShellBar.spec.js | 45 +- .../fiori/test/specs/SideNavigation.spec.js | 51 +- packages/fiori/test/specs/Wizard.spec.js | 6 +- packages/main/src/Breadcrumbs.hbs | 4 +- packages/main/src/Breadcrumbs.ts | 18 +- packages/main/src/ColorPalette.hbs | 8 +- packages/main/src/ColorPalette.ts | 30 +- packages/main/src/ColorPaletteDialog.hbs | 2 + packages/main/src/ComboBox.hbs | 2 + packages/main/src/ComboBox.ts | 19 +- packages/main/src/DatePicker.hbs | 47 +- packages/main/src/DatePicker.ts | 15 +- packages/main/src/DatePickerInput.hbs | 45 + packages/main/src/DateTimePicker.hbs | 2 + packages/main/src/DateTimePicker.ts | 14 +- packages/main/src/Dialog.ts | 5 +- packages/main/src/FileUploader.hbs | 3 +- packages/main/src/FileUploader.ts | 22 +- packages/main/src/Input.hbs | 4 +- packages/main/src/Input.ts | 17 +- packages/main/src/Menu.ts | 15 +- packages/main/src/MultiComboBox.hbs | 2 + packages/main/src/MultiComboBox.ts | 123 +-- packages/main/src/MultiComboBoxPopover.hbs | 1 + packages/main/src/MultiInput.ts | 4 +- packages/main/src/NavigationMenu.ts | 10 +- packages/main/src/Popover.ts | 10 +- packages/main/src/Popup.hbs | 3 +- packages/main/src/Popup.ts | 55 +- packages/main/src/PopupBlockLayer.hbs | 6 +- packages/main/src/ResponsivePopover.hbs | 1 + packages/main/src/ResponsivePopover.ts | 7 - packages/main/src/Select.hbs | 2 + packages/main/src/Select.ts | 28 +- packages/main/src/Tab.ts | 2 +- packages/main/src/TabContainer.hbs | 4 +- packages/main/src/TabContainer.ts | 34 +- packages/main/src/TabContainerPopover.hbs | 1 + packages/main/src/TabSeparator.ts | 2 +- packages/main/src/TextArea.hbs | 2 + packages/main/src/TextArea.ts | 16 +- packages/main/src/TimePicker.hbs | 2 + packages/main/src/TimePickerBase.ts | 48 +- packages/main/src/TimePickerPopover.hbs | 4 +- packages/main/src/Toast.ts | 2 - packages/main/src/Tokenizer.hbs | 4 +- packages/main/src/Tokenizer.ts | 11 +- packages/main/src/Toolbar.hbs | 4 +- packages/main/src/Toolbar.ts | 35 +- packages/main/src/ToolbarButton.ts | 5 +- packages/main/src/ToolbarRegistry.ts | 5 - .../main/src/features/InputSuggestions.ts | 15 +- ...eStaticArea.css => ColorPaletteDialog.css} | 0 packages/main/src/themes/Popup.css | 7 +- ...aticAreaStyles.css => PopupBlockLayer.css} | 11 +- packages/main/src/themes/PopupsCommon.css | 1 - ...ers.css => PopupBlockLayer-parameters.css} | 0 .../themes/sap_belize/parameters-bundle.css | 2 +- .../sap_belize_hcb/parameters-bundle.css | 2 +- .../sap_belize_hcw/parameters-bundle.css | 2 +- .../themes/sap_fiori_3/parameters-bundle.css | 2 +- .../sap_fiori_3_dark/parameters-bundle.css | 2 +- .../sap_fiori_3_hcb/parameters-bundle.css | 2 +- .../sap_fiori_3_hcw/parameters-bundle.css | 2 +- .../themes/sap_horizon/parameters-bundle.css | 2 +- .../sap_horizon_dark/parameters-bundle.css | 2 +- .../sap_horizon_hcb/parameters-bundle.css | 2 +- .../sap_horizon_hcw/parameters-bundle.css | 2 +- .../test/pageobjects/DatePickerTestPage.js | 76 +- .../test/pageobjects/TabContainerTestPage.js | 5 +- packages/main/test/specs/Breadcrumbs.spec.js | 15 +- packages/main/test/specs/ColorPalette.spec.js | 3 +- .../main/test/specs/ComboBox.mobile.spec.js | 65 +- packages/main/test/specs/ComboBox.spec.js | 103 +-- packages/main/test/specs/DatePicker.spec.js | 5 +- .../main/test/specs/DateRangePicker.spec.js | 13 +- .../main/test/specs/DateTimePicker.spec.js | 3 +- packages/main/test/specs/Dialog.spec.js | 62 +- packages/main/test/specs/Input.mobile.spec.js | 49 +- packages/main/test/specs/Input.spec.js | 131 +-- .../main/test/specs/LitKeyFunction.spec.js | 4 +- packages/main/test/specs/Menu.spec.js | 116 ++- .../test/specs/MultiComboBox.mobile.spec.js | 114 +-- .../main/test/specs/MultiComboBox.spec.js | 203 ++--- .../main/test/specs/MultiInput.mobile.spec.js | 21 +- packages/main/test/specs/MultiInput.spec.js | 85 +- packages/main/test/specs/Popover.spec.js | 25 +- .../main/test/specs/Select.mobile.spec.js | 4 +- packages/main/test/specs/Select.spec.js | 64 +- .../test/specs/TabContainer.mobile.spec.js | 6 +- packages/main/test/specs/TabContainer.spec.js | 55 +- packages/main/test/specs/TextArea.spec.js | 23 +- .../main/test/specs/TimePicker.mobile.spec.js | 15 +- packages/main/test/specs/TimePicker.spec.js | 17 +- packages/main/test/specs/Toolbar.spec.js | 6 +- .../main/test/specs/ToolbarButton.spec.js | 9 +- .../main/test/specs/ToolbarSelect.spec.js | 3 +- .../build-scripts-storybook/parse-manifest.js | 1 - packages/tools/components-package/wdio.js | 809 +++++++++--------- .../tools/components-package/wdio.sync.js | 368 -------- yarn.lock | 134 +-- 132 files changed, 1468 insertions(+), 3022 deletions(-) delete mode 100644 packages/base/src/StaticAreaItem.ts delete mode 100644 packages/base/test/elements/WithStaticArea.js create mode 100644 packages/main/src/DatePickerInput.hbs create mode 100644 packages/main/src/DateTimePicker.hbs rename packages/main/src/themes/{ColorPaletteStaticArea.css => ColorPaletteDialog.css} (100%) rename packages/main/src/themes/{PopupStaticAreaStyles.css => PopupBlockLayer.css} (69%) rename packages/main/src/themes/base/{PopupStaticAreaStyles-parameters.css => PopupBlockLayer-parameters.css} (100%) delete mode 100644 packages/tools/components-package/wdio.sync.js diff --git a/docs/5-development/05-testing-UI5-Web-Components.md b/docs/5-development/05-testing-UI5-Web-Components.md index 9a215737d965..236aa2f58a78 100644 --- a/docs/5-development/05-testing-UI5-Web-Components.md +++ b/docs/5-development/05-testing-UI5-Web-Components.md @@ -218,32 +218,4 @@ UI5 Web Components versions up to, including, `1.0.0-rc.15`, used to recommend t If you have already written tests for your custom UI5 Web Components using the *synchronous* syntax, and you update to a later version than `1.0.0-rc.15`, your tests will no longer run. You have 2 options: - Rewrite all tests to use the *asynchronous* syntax. Click the link above to see some examples. This is the **recommended** approach, because the *synchronous* syntax will no longer work with future `nodejs` versions. - - For the time being, adapt your WebdriverIO configuration to continue supporting the *synchronous* syntax. - -### 5.1 Supporting the synchronous syntax for writing tests - - - Change your `config/wdio.conf.js` file's content from: - - ```js - module.exports = require("@ui5/webcomponents-tools/components-package/wdio.js"); - ``` - to: - - ```js - module.exports = require("@ui5/webcomponents-tools/components-package/wdio.sync.js"); - ``` - - This will give you the exact same WebdriverIO configuration, but with *synchronous* custom commands (such as `getProperty`, `setProperty`, `hasClass`, etc.). - - - Manually install `@wdio/sync` - - You can install it with `npm`: - - `npm i --save-dev @wdio/sync` - - or with `yarn`: - - `yarn add -D @wdio/sync` - - Just installing the package (with no extra configuration) is enough to let WebdriverIO run the *synchronous* tests. - + - For the time being, adapt your WebdriverIO configuration to continue supporting the *synchronous* syntax. \ No newline at end of file diff --git a/docs/5-development/06-deep-dive-and-best-practices.md b/docs/5-development/06-deep-dive-and-best-practices.md index c99795930e96..7fccbed926b6 100644 --- a/docs/5-development/06-deep-dive-and-best-practices.md +++ b/docs/5-development/06-deep-dive-and-best-practices.md @@ -25,11 +25,6 @@ as this article will expand on many of the notions, introduced there. - [`onBeforeRendering`](#lifecycle_before) - [`onAfterRendering`](#lifecycle_after) - [`onEnterDOM` and `onExitDOM`](#lifecycle_dom) -4. [The static area](#static) - - [Preface](#static_preface) - - [What is the static area and why is it needed?](#static_what_why) - - [Using the static area?](#static_using) - - [Accessing the static area item](#static_accessing) ## Metadata deep dive @@ -1086,314 +1081,3 @@ and then in `onEnterDOM` and `onExitDOM` we register/deregister this function wi Then, whenever the component resizes, the `ResizeHandler` will trigger the callback, the metadata `_width` property will be updated to a new value in `_onResize`, the component will be invalidated, and the template will be executed with the new value of `_width`, respectively `styles`. - -## The static area - -### Preface - -This section expands on the UI5 Web Components class structure, so if you haven't, please check [Developing Custom UI5 Web Components](./02-custom-UI5-Web-Components.md) first. - -Normally, the whole HTML markup of a UI5 Web Component is found in one place - the shadow DOM of the custom element itself. - -Example: - -```html -Click me -``` - -All HTML, belonging to this `ui5-button` instance is in its own shadow DOM. - -Respectively, in the class where the button component is defined, we provide one template and one piece of CSS: - -```js -import ButtonTemplate from "./generated/templates/ButtonTemplate.lit.js"; -import buttonCss from "./generated/themes/Button.css.js"; - -class Button extends UI5Element { - ... - - static get styles() { - return buttonCss; - } - - static get template() { - return ButtonTemplate; - } - -} -``` - -These are respectively the template and CSS that are going to be used in the component's shadow DOM. - -However, there are more complex components, whose HTML is split in two parts - the custom element's shadow DOM (as is the case with the button), -but also a so called **static area** part, holding all popups this component might open. This is the case with most components that have any kind of -popup-related functionality (dropdowns, rich tooltips, popovers, dialogs). Prominent examples are `ui5-select`, `ui5-combobox`, `ui5-textarea`, `ui5-date-picker`. - -### What is the static area and why is it needed? - -The static area is a special *singleton* custom element (`ui5-static-area`), placed automatically by the framework as the first child of the `body`. -For each component, having a **static area** part, a `ui5-static-area-item` custom element is created inside the static area. - -```html - - - - - - - - - - -``` - -In this example 3 UI5 Web Components are used: `ui5-select`, `ui5-date-picker`, and `ui5-button`. -Since two of them have static area parts, the framework has created a `ui5-static-area` (one for the whole page) and inside it a `ui5-static-area-item` -for each component with a static area part. - -Thus, the HTML, defining the `ui5-select` and `ui5-date-picker` components is split in two parts of the HTML page: - - the shadow DOM of the custom element itself (`ui5-select`, `ui5-date-picker`) - - the shadow DOM of the `static-area-item`, created for the respective component. - -**This is necessary because such a split is the only way to guarantee that a popup (dropdown, rich tooltip, popover, etc.) will always be -positioned correctly on the HTML page**, even if parts of the page have: - - `transform: translate` - - `overflow: hidden` - - `z-index` - -Since the `ui5-statia-area` is a top-level `body` child, it is guaranteed to be on top of everything else on the page with the correct CSS styles, -regardless of the page structure and [stacking context](https://developer.mozilla.org/en-US/docs/Glossary/Stacking_context). - -If we did not use a static area, for example as in a component, defined like this: - -In the `MySelect.js` file: - -```handlebars -
-

Click to open the dropdown:

- - - - - {{#each dropdownItems}} - {{text}} - {{/each}} - - -
-``` - -In the `MySelect.js` file: - -```js -class MySelect extends UI5Element { - ... - onOpenDropdownClick(event) { - this.dropdownOpen = true; - } -} -``` - -then when the user clicks the `button`, and the `ui5-popover` opens (due to its `open` property having been set to `true`), -this popover might be partially or entirely "cut" or misplaced, depending on the position of the component on the page. - -Example 1: - -```html - - - -``` - -Here the `my-select` component would work just fine as it is the only component on the page and no other components create a stacking context or overflow. - -However, consider example 2: - -```html - -
- -
- -``` - -Now, when the popover opens, only a `20px`-high strip of it would be visible due to the parent element's CSS. - -This is an oversimplified example that could easily be fixed, but in real-world scenarios there are often parts of the HTML page we cannot -influence which cause problems with popups. - -### Using the static area - -Here is how we can rework the component from the example above to take advantage of the static area: - -1. Split the template and CSS of the component: - -Instead of having the dropdown (`ui5-popover`) in the main template: - -```handlebars -
-

Click to open the dropdown:

- - - - - {{#each dropdownItems}} - {{text}} - {{/each}} - - -
-``` - -split `MySelect.hbs` into `MySelect.hbs` and `MySelectDropdown.hbs`: - -The `MySelect.hbs` file: - -```handlebars -
-

Click to open the dropdown:

- -
-``` - -The `MySelectDropdown.hbs` file: - -```handlebars - - - {{#each dropdownItems}} - {{text}} - {{/each}} - - -``` - -Also, create the CSS of the component in 2 files: - - `MySelect.css` (with styles for the select itself, f.e. `.my-select {}`) - - `MySelectDropdown.css` (with styles for the dropdown only, f.e. `#dropdown {}`) - -2. Pass the new template and CSS to the component class - -The `MySelect.js` file: - -```js -import MySelectTemplate from "./generated/templates/MySelect.lit.js"; -import MySelectDropdownTemplate from "./generated/templates/MySelectDropdown.lit.js"; - -import mySelectCss from "./generated/themes/MySelect.css.js"; -import mySelectDropdownCss from "./generated/themes/MySelectDropdown.css.js"; - -class MySelect extends UI5Element { - ... - - static get styles() { - return mySelectCss; - } - - static get staticAreaStyles() { - return mySelectDropdownCss; - } - - static get template() { - return MySelectTemplate; - } - - static get staticAreaTemplate() { - return MySelectDropdownTemplate; - } - -} -``` - -Creating the `static get staticAreaTemplate()` method is the indication that your component has a static area part, -and will trigger the respective framework functionality to support it. - -3. Use the `async getStaticAreaItemDomRef()` method to create the static area item **on demand**, whenever necessary. - -```js -class MySelect extends UI5Element { - ... - - async onOpenDropdownClick() { - await this.getStaticAreaItemDomRef(); // this line is new compared to the old implementation - this.dropdownOpen = true; - } - -} -``` - -This is all it takes to make your component work with the static area. - -**Important:** please note that the static area item is only created **on demand** - when you call the `async getStaticAreaItemDomRef()` function. -For most components this is when the user opens a menu/dropdown/hovers over an element for a tooltip, etc. - -Let's go over the whole process in more detail: - - 1. The browser renders a `` component: - -```html - - - -``` - -The shadow root of the `my-select` component will be created with the content from the `MySelect.hbs` template, as it was provided as `static get template()`. -Note that until this point nothing related to the static area has happened. The lifecycle of this component so far is not much different than that of a `ui5-button`. - -2. The user interacts with the component (clicks the "Dropdown" button) - -This will trigger the `onOpenDropdownClick` event handler we've bound in `MySelect.hbs` -and once the first line of this event handler is executed (the `await this.getStatiAreaItemDomRef` part): - -```js -async onOpenDropdownClick() { - await this.getStaticAreaItemDomRef(); - this.dropdownOpen = true; -} -``` - -the framework will create the `ui5-static-area` and a `ui5-static-area-item` and will create its shadow root with the content from the `MySelectDropdown.hbs` template, as it was provided as `static get staticAreaTemplate()`. - -The DOM would then look like this: - -```html - - - - #shadow-root - - - - - #shadow-root - - -``` - -If the user hadn't clicked the button, the static area part would not have been created at all. - -### Accessing the static area item - -The `async getStaticAreaItemDomRef()` function from the example above: - -```js -async onOpenDropdownClick() { - await this.getStaticAreaItemDomRef(); - this.dropdownOpen = true; -} -``` - -returns a reference to the `shadowRoot` of the static area item for this component. - -You can therefore access it like this: - -```js -const staticAreaItem = await this.getStaticAreaItemDomRef(); -const popover = staticAreaItem.querySelector("[ui5-popover]"); -``` - -First, we get a reference to the static area item's shadow root in `staticAreaItem`, and then we get the instance of the `ui5-popover` element -by using the attribute selector (`[ui5-popover]`), as is the best practice. See [Tag](#metadata_tag) in the [Metadata deep dive](#metadata) section above. - -Also, note that no matter how many times you call `getStaticAreaItemDomRef`, the static area item will be created only the first time. - diff --git a/docs/5-development/07-typescript-in-UI5-Web-Components.md b/docs/5-development/07-typescript-in-UI5-Web-Components.md index c0dbe7542271..c888334e3556 100644 --- a/docs/5-development/07-typescript-in-UI5-Web-Components.md +++ b/docs/5-development/07-typescript-in-UI5-Web-Components.md @@ -677,9 +677,8 @@ It's important to note that casting the returned result will exclude "`null`." A ```ts -async _getDialog() { - const staticAreaItem = await this.getStaticAreaItemDomRef(); - return staticAreaItem!.querySelector("[ui5-dialog]")!; +_getDialog() { + return this.shadowRoot!.querySelector("[ui5-dialog]")!; } ``` diff --git a/packages/base/bundle.esm.js b/packages/base/bundle.esm.js index ddebbbad9e7d..8712b457b7ad 100644 --- a/packages/base/bundle.esm.js +++ b/packages/base/bundle.esm.js @@ -9,7 +9,6 @@ import "./test/elements/Generic.js"; import "./test/elements/NoShadowDOM.js"; import "./test/elements/Parent.js"; import "./test/elements/Child.js"; -import "./test/elements/WithStaticArea.js"; import "./test/elements/WithComplexTemplate.js"; import "./test/elements/GenericExt.js"; diff --git a/packages/base/config/wdio.conf.cjs b/packages/base/config/wdio.conf.cjs index 064e4ade4c25..db5ed6d063c3 100644 --- a/packages/base/config/wdio.conf.cjs +++ b/packages/base/config/wdio.conf.cjs @@ -230,13 +230,6 @@ exports.config = { }, this, attrName); }, true); - await browser.addCommand("getStaticAreaItemClassName", async function(selector) { - return browser.executeAsync(async (selector, done) => { - const staticAreaItem = await document.querySelector(selector).getStaticAreaItemDomRef(); - done(staticAreaItem.host.classList[0]); - }, selector); - }, false); - await browser.addLocatorStrategy('activeElement', (selector) => { return document.querySelector(selector).shadowRoot.activeElement; }); @@ -256,7 +249,6 @@ exports.config = { "getHTML", "getProperty", "getSize", - "getStaticAreaItemClassName", // custom "getText", "getValue", "hasClass", // custom diff --git a/packages/base/src/StaticAreaItem.ts b/packages/base/src/StaticAreaItem.ts deleted file mode 100644 index d3aa70ef7950..000000000000 --- a/packages/base/src/StaticAreaItem.ts +++ /dev/null @@ -1,115 +0,0 @@ -import "./StaticArea.js"; -import updateShadowRoot from "./updateShadowRoot.js"; -import { renderFinished } from "./Render.js"; -import getEffectiveContentDensity from "./util/getEffectiveContentDensity.js"; -import { getEffectiveScopingSuffixForTag } from "./CustomElementsScopeUtils.js"; -import getEffectiveDir from "./locale/getEffectiveDir.js"; -import type UI5Element from "./UI5Element.js"; - -const pureTagName = "ui5-static-area-item"; -const popupIntegrationAttr = "data-sap-ui-integration-popup-content"; - -/** - * @class - * @private - */ -class StaticAreaItem extends HTMLElement { - _rendered: boolean; - ownerElement?: UI5Element; - - constructor() { - super(); - this._rendered = false; - this.attachShadow({ mode: "open" }); - } - - /** - * @param ownerElement the UI5Element instance that owns this static area item - */ - setOwnerElement(ownerElement: UI5Element) { - this.ownerElement = ownerElement; - this.classList.add(this.ownerElement._id); // used for getting the popover in the tests - if (this.ownerElement.hasAttribute("data-ui5-static-stable")) { - this.setAttribute("data-ui5-stable", this.ownerElement.getAttribute("data-ui5-static-stable")!); // stable selector - } - } - - /** - * Updates the shadow root of the static area item with the latest state, if rendered - */ - update() { - if (this._rendered) { - this.updateAdditionalProperties(); - updateShadowRoot(this.ownerElement!, true); - } - } - - updateAdditionalProperties() { - this._updateAdditionalAttrs(); - this._updateContentDensity(); - this._updateDirection(); - } - - /** - * Sets the correct content density based on the owner element's state - * @private - */ - _updateContentDensity() { - if (getEffectiveContentDensity(this.ownerElement!) === "compact") { - this.classList.add("sapUiSizeCompact"); - this.classList.add("ui5-content-density-compact"); - } else { - this.classList.remove("sapUiSizeCompact"); - this.classList.remove("ui5-content-density-compact"); - } - } - - _updateDirection() { - if (this.ownerElement) { - const dir = getEffectiveDir(this.ownerElement); - if (dir === "rtl") { - this.setAttribute("dir", dir); - } else { - this.removeAttribute("dir"); - } - } - } - - _updateAdditionalAttrs() { - this.setAttribute(pureTagName, ""); - this.setAttribute(popupIntegrationAttr, ""); - } - - /** - * Returns reference to the DOM element where the current fragment is added. - * @protected - */ - async getDomRef() { - this.updateAdditionalProperties(); - if (!this._rendered) { - this._rendered = true; - updateShadowRoot(this.ownerElement!, true); - } - await renderFinished(); // Wait for the content of the ui5-static-area-item to be rendered - return this.shadowRoot; - } - - static getTag() { - const suffix = getEffectiveScopingSuffixForTag(pureTagName); - if (!suffix) { - return pureTagName; - } - - return `${pureTagName}-${suffix}`; - } - - static createInstance() { - if (!customElements.get(StaticAreaItem.getTag())) { - customElements.define(StaticAreaItem.getTag(), StaticAreaItem); - } - - return document.createElement(this.getTag()) as StaticAreaItem; - } -} - -export default StaticAreaItem; diff --git a/packages/base/src/UI5Element.ts b/packages/base/src/UI5Element.ts index 93529993abe9..c70ce3e3d750 100644 --- a/packages/base/src/UI5Element.ts +++ b/packages/base/src/UI5Element.ts @@ -10,11 +10,13 @@ import UI5ElementMetadata, { Metadata, } from "./UI5ElementMetadata.js"; import EventProvider from "./EventProvider.js"; -import getSingletonElementInstance from "./util/getSingletonElementInstance.js"; -import StaticAreaItem from "./StaticAreaItem.js"; import updateShadowRoot from "./updateShadowRoot.js"; import { shouldIgnoreCustomElement } from "./IgnoreCustomElements.js"; -import { renderDeferred, renderImmediately, cancelRender } from "./Render.js"; +import { + renderDeferred, + renderImmediately, + cancelRender, +} from "./Render.js"; import { registerTag, isTagRegistered, recordTagRegistrationFailure } from "./CustomElementsRegistry.js"; import { observeDOMNode, unobserveDOMNode } from "./DOMObserver.js"; import { skipOriginalEvent } from "./config/NoConflict.js"; @@ -34,7 +36,7 @@ let autoId = 0; const elementTimeouts = new Map>(); const uniqueDependenciesCache = new Map>(); -type Renderer = (templateResult: TemplateFunctionResult, container: HTMLElement | DocumentFragment, forStaticArea: boolean, options: RendererOptions) => void; +type Renderer = (templateResult: TemplateFunctionResult, container: HTMLElement | DocumentFragment, options: RendererOptions) => void; type RendererOptions = { /** @@ -102,10 +104,7 @@ abstract class UI5Element extends HTMLElement { _state: State; _getRealDomRef?: () => HTMLElement; - staticAreaItem?: StaticAreaItem; - static template?: TemplateFunction; - static staticAreaTemplate?: TemplateFunction; static _metadata: UI5ElementMetadata; static renderer: Renderer; @@ -157,11 +156,6 @@ abstract class UI5Element extends HTMLElement { return executeTemplate(template!, this); } - renderStatic() { - const template = (this.constructor as typeof UI5Element).staticAreaTemplate; - return executeTemplate(template!, this); - } - /** * Do not call this method from derivatives of UI5Element, use "onEnterDOM" only * @private @@ -213,10 +207,6 @@ abstract class UI5Element extends HTMLElement { this._fullyConnected = false; } - if (this.staticAreaItem && this.staticAreaItem.parentElement) { - this.staticAreaItem.parentElement.removeChild(this.staticAreaItem); - } - cancelRender(this); } @@ -641,9 +631,9 @@ abstract class UI5Element extends HTMLElement { * 1) children: immediate children (HTML elements or text nodes) were added, removed or reordered in the slot * 2) textcontent: text nodes in the slot changed value (or nested text nodes were added or changed value). Can only trigger for slots of "type: Node" * 3) slotchange: a slot element, slotted inside that slot had its "slotchange" event listener called. This practically means that transitively slotted children changed. - * Can only trigger if the child of a slot is a slot element itself. + * Can only trigger if the child of a slot is a slot element itself. * 4) childchange: indicates that a UI5Element child in that slot was invalidated and in turn invalidated the component. - * Can only trigger for slots with "invalidateOnChildChange" metadata descriptor + * Can only trigger for slots with "invalidateOnChildChange" metadata descriptor * * - newValue: the new value of the property (for type="property" only) * @@ -701,9 +691,6 @@ abstract class UI5Element extends HTMLElement { if (ctor._needsShadowDOM()) { updateShadowRoot(this); } - if (this.staticAreaItem) { - this.staticAreaItem.update(); - } // Safari requires that children get the slot attribute only after the slot tags have been rendered in the shadow DOM if (hasIndividualSlots) { @@ -751,12 +738,7 @@ abstract class UI5Element extends HTMLElement { return; } - const children = [...this.shadowRoot.children].filter(child => !["link", "style"].includes(child.localName)); - if (children.length !== 1) { - console.warn(`The shadow DOM for ${(this.constructor as typeof UI5Element).getMetadata().getTag()} does not have a top level element, the getDomRef() method might not work as expected`); // eslint-disable-line - } - - return children[0] as HTMLElement; + return this.shadowRoot.children[0] as HTMLElement; } /** @@ -915,32 +897,6 @@ abstract class UI5Element extends HTMLElement { return !!this.template || Object.prototype.hasOwnProperty.call(this.prototype, "render"); } - /** - * @private - */ - static _needsStaticArea() { - return !!this.staticAreaTemplate || Object.prototype.hasOwnProperty.call(this.prototype, "renderStatic"); - } - - /** - * @public - */ - getStaticAreaItemDomRef(): Promise { - if (!(this.constructor as typeof UI5Element)._needsStaticArea()) { - throw new Error("This component does not use the static area"); - } - - if (!this.staticAreaItem) { - this.staticAreaItem = StaticAreaItem.createInstance(); - this.staticAreaItem.setOwnerElement(this); - } - if (!this.staticAreaItem.parentElement) { - getSingletonElementInstance("ui5-static-area").appendChild(this.staticAreaItem); - } - - return this.staticAreaItem.getDomRef(); - } - /** * @private */ @@ -1062,14 +1018,6 @@ abstract class UI5Element extends HTMLElement { */ static styles: ComponentStylesData = ""; - /** - * Returns the Static Area CSS for this UI5 Web Component Class - * @protected - */ - static get staticAreaStyles(): ComponentStylesData { - return ""; - } - /** * Returns an array with the dependencies for this UI5 Web Component, which could be: * - composed components (used in its shadow root or static area item) @@ -1169,7 +1117,9 @@ const instanceOfUI5Element = (object: any): object is UI5Element => { }; export default UI5Element; -export { instanceOfUI5Element }; +export { + instanceOfUI5Element, +}; export type { ChangeInfo, Renderer, diff --git a/packages/base/src/decorators/customElement.ts b/packages/base/src/decorators/customElement.ts index 163813675592..b719c89da968 100644 --- a/packages/base/src/decorators/customElement.ts +++ b/packages/base/src/decorators/customElement.ts @@ -15,8 +15,6 @@ const customElement = (tagNameOrComponentSettings: string | { styles?: Styles, template?: Template, dependencies?: Array, - staticAreaStyles?: Styles, - staticAreaTemplate?: Template, languageAware?: boolean, themeAware?: boolean, fastNavigation?: boolean, @@ -49,7 +47,7 @@ const customElement = (tagNameOrComponentSettings: string | { target.metadata.fastNavigation = fastNavigation; } - ["renderer", "template", "staticAreaTemplate", "styles", "staticAreaStyles", "dependencies"].forEach((customElementEntity: string) => { + ["renderer", "template", "styles", "dependencies"].forEach((customElementEntity: string) => { const customElementEntityValue = tagNameOrComponentSettings[customElementEntity as keyof typeof tag]; customElementEntityValue && Object.defineProperty(target, customElementEntity, { diff --git a/packages/base/src/features/OpenUI5Support.ts b/packages/base/src/features/OpenUI5Support.ts index b634d78017ce..4803b5007a93 100644 --- a/packages/base/src/features/OpenUI5Support.ts +++ b/packages/base/src/features/OpenUI5Support.ts @@ -1,14 +1,8 @@ import { registerFeature } from "../FeaturesRegistry.js"; import { setTheme } from "../config/Theme.js"; -import { getCurrentZIndex } from "../util/PopupUtils.js"; import { CLDRData } from "../asset-registries/LocaleData.js"; import type { LegacyDateCalendarCustomizing } from "../features/LegacyDateFormats.js"; -type OpenUI5Popup = { - setInitialZIndex: (zIndex: number) => void, - getNextZIndex: () => number, -}; - type OpenUI5Core = { attachInit: (callback: () => void) => void, ready: () => Promise, @@ -90,7 +84,7 @@ class OpenUI5Support { return new Promise(resolve => { window.sap.ui.require(["sap/ui/core/Core"], async (Core: OpenUI5Core) => { const callback = () => { - let deps: Array = ["sap/ui/core/Popup", "sap/ui/core/LocaleData"]; + let deps: Array = ["sap/ui/core/LocaleData"]; if (OpenUI5Support.isAtLeastVersion116()) { // for versions since 1.116.0 and onward, use the modular core deps = [ ...deps, @@ -101,10 +95,7 @@ class OpenUI5Support { "sap/ui/core/date/CalendarUtils", ]; } - window.sap.ui.require(deps, (Popup: OpenUI5Popup) => { - Popup.setInitialZIndex(getCurrentZIndex()); - resolve(); - }); + window.sap.ui.require(deps, resolve); }; if (OpenUI5Support.isAtLeastVersion116()) { await Core.ready(); @@ -215,29 +206,6 @@ class OpenUI5Support { return !!link.href.match(/\/css(-|_)variables\.css/); } - - static getNextZIndex() { - if (!OpenUI5Support.isOpenUI5Detected()) { - return; - } - - const Popup = window.sap.ui.require("sap/ui/core/Popup") as OpenUI5Popup; - - if (!Popup) { - console.warn(`The OpenUI5Support feature hasn't been initialized properly. Make sure you import the "@ui5/webcomponents-base/dist/features/OpenUI5Support.js" module before all components' modules.`); // eslint-disable-line - } - - return Popup.getNextZIndex(); - } - - static setInitialZIndex() { - if (!OpenUI5Support.isOpenUI5Detected()) { - return; - } - - const Popup = window.sap.ui.require("sap/ui/core/Popup") as OpenUI5Popup; - Popup.setInitialZIndex(getCurrentZIndex()); - } } registerFeature("OpenUI5Support", OpenUI5Support); diff --git a/packages/base/src/renderer/LitRenderer.ts b/packages/base/src/renderer/LitRenderer.ts index 7b76c0dbd6c3..a8dd72ddfa8f 100644 --- a/packages/base/src/renderer/LitRenderer.ts +++ b/packages/base/src/renderer/LitRenderer.ts @@ -24,9 +24,9 @@ const effectiveSvg = (strings: TemplateStringsArray, ...values: Array) return fn(strings, ...values); }; -const litRender: Renderer = (templateResult: TemplateFunctionResult, container: HTMLElement | DocumentFragment, forStaticArea: boolean, options: RendererOptions) => { +const litRender: Renderer = (templateResult: TemplateFunctionResult, container: HTMLElement | DocumentFragment, options: RendererOptions) => { const openUI5Enablement = getFeature("OpenUI5Enablement"); - if (openUI5Enablement && !forStaticArea) { + if (openUI5Enablement) { templateResult = openUI5Enablement.wrapTemplateResultInBusyMarkup(effectiveHtml, options.host as UI5Element, templateResult as TemplateResult); } diff --git a/packages/base/src/theming/getConstructableStyle.ts b/packages/base/src/theming/getConstructableStyle.ts index 3b1a85817f46..865772d73d3a 100644 --- a/packages/base/src/theming/getConstructableStyle.ts +++ b/packages/base/src/theming/getConstructableStyle.ts @@ -14,12 +14,12 @@ attachCustomCSSChange((tag: string) => { * @param ElementClass * @returns {*} */ -const getConstructableStyle = (ElementClass: typeof UI5Element, forStaticArea = false) => { +const getConstructableStyle = (ElementClass: typeof UI5Element) => { const tag = ElementClass.getMetadata().getTag(); - const key = `${tag}_${forStaticArea ? "static" : "normal"}`; + const key = `${tag}_normal`; if (!constructableStyleMap.has(key)) { - const styleContent = getEffectiveStyle(ElementClass, forStaticArea); + const styleContent = getEffectiveStyle(ElementClass); const style = new CSSStyleSheet(); style.replaceSync(styleContent); constructableStyleMap.set(key, [style]); diff --git a/packages/base/src/theming/getEffectiveStyle.ts b/packages/base/src/theming/getEffectiveStyle.ts index 1d6ddb4dd918..d7e4d340b5a8 100644 --- a/packages/base/src/theming/getEffectiveStyle.ts +++ b/packages/base/src/theming/getEffectiveStyle.ts @@ -10,28 +10,22 @@ attachCustomCSSChange((tag: string) => { effectiveStyleMap.delete(`${tag}_normal`); // there is custom CSS only for the component itself, not for its static area part }); -const getEffectiveStyle = (ElementClass: typeof UI5Element, forStaticArea = false) => { +const getEffectiveStyle = (ElementClass: typeof UI5Element) => { const tag = ElementClass.getMetadata().getTag(); - const key = `${tag}_${forStaticArea ? "static" : "normal"}`; + const key = `${tag}_normal`; const openUI5Enablement = getFeature("OpenUI5Enablement"); if (!effectiveStyleMap.has(key)) { - let effectiveStyle; let busyIndicatorStyles = ""; if (openUI5Enablement) { busyIndicatorStyles = getStylesString(openUI5Enablement.getBusyIndicatorStyles()); } - if (forStaticArea) { - effectiveStyle = getStylesString(ElementClass.staticAreaStyles); - } else { - const customStyle = getCustomCSS(tag) || ""; - const builtInStyles = getStylesString(ElementClass.styles); - effectiveStyle = `${builtInStyles} ${customStyle}`; - } + const customStyle = getCustomCSS(tag) || ""; + const builtInStyles = getStylesString(ElementClass.styles); - effectiveStyle = `${effectiveStyle} ${busyIndicatorStyles}`; + const effectiveStyle = `${builtInStyles} ${customStyle} ${busyIndicatorStyles}`; effectiveStyleMap.set(key, effectiveStyle); } diff --git a/packages/base/src/updateShadowRoot.ts b/packages/base/src/updateShadowRoot.ts index 6a4c1fba880d..7564f4afffb8 100644 --- a/packages/base/src/updateShadowRoot.ts +++ b/packages/base/src/updateShadowRoot.ts @@ -4,26 +4,20 @@ import type UI5Element from "./UI5Element.js"; /** * Updates the shadow root of a UI5Element or its static area item * @param element - * @param forStaticArea */ -const updateShadowRoot = (element: UI5Element, forStaticArea = false) => { +const updateShadowRoot = (element: UI5Element) => { const ctor = element.constructor as typeof UI5Element; - const shadowRoot = forStaticArea ? element.staticAreaItem!.shadowRoot : element.shadowRoot; - let renderResult; - if (forStaticArea) { - renderResult = element.renderStatic(); // this is checked before calling updateShadowRoot - } else { - renderResult = element.render(); // this is checked before calling updateShadowRoot - } + const shadowRoot = element.shadowRoot; + const renderResult = element.render(); // this is checked before calling updateShadowRoot if (!shadowRoot) { console.warn(`There is no shadow root to update`); // eslint-disable-line return; } - shadowRoot.adoptedStyleSheets = getConstructableStyle(ctor, forStaticArea); + shadowRoot.adoptedStyleSheets = getConstructableStyle(ctor); - ctor.renderer(renderResult, shadowRoot, forStaticArea, { host: element }); + ctor.renderer(renderResult, shadowRoot, { host: element }); }; export default updateShadowRoot; diff --git a/packages/base/src/util/PopupUtils.ts b/packages/base/src/util/PopupUtils.ts index 3e18f1706352..ce087a380051 100644 --- a/packages/base/src/util/PopupUtils.ts +++ b/packages/base/src/util/PopupUtils.ts @@ -1,13 +1,4 @@ -import getSharedResource from "../getSharedResource.js"; -import { getFeature } from "../FeaturesRegistry.js"; import getActiveElement from "./getActiveElement.js"; -import type OpenUI5Support from "../features/OpenUI5Support.js"; - -type PopupUtilsData = { - currentZIndex: number -}; - -const popupUtilsData = getSharedResource("PopupUtilsData", { currentZIndex: 100 }); const getFocusedElement = () => { const element = getActiveElement() as HTMLElement; @@ -88,25 +79,9 @@ const getClosedPopupParent = (el: HTMLElement): HTMLElement => { return getClosedPopupParent(parent as HTMLElement); }; -const getNextZIndex = () => { - const openUI5Support = getFeature("OpenUI5Support"); - if (openUI5Support && openUI5Support.isOpenUI5Detected()) { // use OpenUI5 for getting z-index values, if loaded - return openUI5Support.getNextZIndex(); - } - - popupUtilsData.currentZIndex += 2; - return popupUtilsData.currentZIndex; -}; - -const getCurrentZIndex = () => { - return popupUtilsData.currentZIndex; -}; - export { getFocusedElement, isClickInRect, getClosedPopupParent, - getNextZIndex, - getCurrentZIndex, isFocusedElementWithinNode, }; diff --git a/packages/base/test/elements/WithStaticArea.js b/packages/base/test/elements/WithStaticArea.js deleted file mode 100644 index eba6e0d642a7..000000000000 --- a/packages/base/test/elements/WithStaticArea.js +++ /dev/null @@ -1,77 +0,0 @@ -import UI5Element from "../../dist/UI5Element.js"; -import litRender, { html } from "../../dist/renderer/LitRenderer.js"; - -const metadata = { - tag: "ui5-with-static-area", - properties: { - /** - * Defines whether the static area item will be rendered - */ - staticContent: { - type: Boolean, - } - }, - slots: { - - } -}; - -class WithStaticArea extends UI5Element { - static get metadata() { - return metadata; - } - - static get renderer() { - return litRender; - } - - static get template() { - return element => { - // access effectiveDir getter to mark control as RTL-aware (test changes dir attribute and expects rerender) - return html` -
- WithStaticArea works! -
`; - }; - } - - static get staticAreaTemplate() { - return element => { - return html` -
- Static area content. -
`; - }; - } - - static get styles() { - return ` - :host { - display: inline-block; - border: 1px solid black; - color: red; - }`; - } - - async addStaticArea() { - if (!this.staticContent) { - return; - } - - // Require static area item - const staticArea = await this.getStaticAreaItemDomRef(); - this.responsivePopover = staticArea.querySelector(".ui5-with-static-area-content"); - return this.responsivePopover; - } - - onBeforeRendering() { - this.addStaticArea(); - } - onAfterRendering() {} - onEnterDOM() {} - onExitDOM() {} -} - -WithStaticArea.define(); - -export default WithStaticArea; diff --git a/packages/base/test/specs/SystemDOMElements.spec.js b/packages/base/test/specs/SystemDOMElements.spec.js index 86a76d126aa6..4fc755dfe0cf 100644 --- a/packages/base/test/specs/SystemDOMElements.spec.js +++ b/packages/base/test/specs/SystemDOMElements.spec.js @@ -1,83 +1,10 @@ import { assert } from "chai"; -describe("Static Area :: runtime changes", () => { +describe("Shared Resources", () => { before(async () => { await browser.url("test/pages/AllTestElements.html"); }); - it("Tests control with no static area item", async () => { - const componentId = await browser.$("#no-static-area").getProperty("_id"); - const staticArea = await browser.$("ui5-static-area"); - - assert.notOk(await staticArea.$(`.${componentId}`).isExisting(), "No static area item is defined for this control"); - }); - - it("Tests control with static area item", async () => { - const componentId = await browser.$("#with-static-area").getProperty("_id"); - const staticArea = await browser.$("ui5-static-area"); - - assert.ok(await staticArea.$(`.${componentId}`).isExisting(), "No static area item is defined for this control"); - }); - - it("Tests removing an element with static area", async () => { - const result = await browser.executeAsync(done => { - let res = true; - window.onerror = (errorMsg, url, lineNumber) => { - res = false; - } - - document.querySelector("#no-static-area").remove(); - - done(res); - }); - - assert.ok(result, "Static area removed from DOM successfully"); - }); - - it("Test RTL not set for static area items", async () => { - const componentId = await browser.$("#with-static-area").getProperty("_id"); - const staticArea = await browser.$("ui5-static-area"); - - assert.notOk(await staticArea.$(`.${componentId}`).getAttribute("dir"), "dir attribute not set for static area item"); - }); - - it("Test RTL set for static area items", async () => { - const componentId = await browser.$("#with-static-area-rtl").getProperty("_id"); - const staticArea = await browser.$("ui5-static-area"); - - assert.equal(await staticArea.$(`.${componentId}`).getAttribute("dir"), "rtl", "dir property correctly set for static area item"); - }); - - it("Test setting RTL for a static area item owner", async () => { - const componentId = await browser.$("#with-static-area").getProperty("_id"); - const staticArea = await browser.$("ui5-static-area"); - - await browser.$("#with-static-area").setAttribute("dir", "rtl"); - await browser.executeAsync( async (done) => { - await window["sap-ui-webcomponents-bundle"].applyDirection(); - await window["sap-ui-webcomponents-bundle"].renderFinished(); - - done(); - }); - assert.equal(await staticArea.$(`.${componentId}`).getAttribute("dir"), "rtl", "dir attribute dynamically set for static area item owner"); - }); - - it("Test removing RTL for a static area item owner", async () => { - const componentId = await browser.$("#with-static-area-rtl").getProperty("_id"); - const staticArea = await browser.$("ui5-static-area"); - - await browser.$("#with-static-area-rtl-container").removeAttribute("dir"); - await browser.executeAsync( async (done) => { - await window["sap-ui-webcomponents-bundle"].applyDirection(); - await window["sap-ui-webcomponents-bundle"].renderFinished(); - - done(); - }); - assert.notOk(await staticArea.$(`.${componentId}`).getAttribute("dir"), "dir attribute dynamically removed for static area item owner"); - }); -}); - -describe("Shared Resources", () => { it("Tests the presense of the shared resources 'meta' element", async () => { const sharedResourcesElement = await browser.executeAsync(done => { return done(document.querySelector(`meta[name="ui5-shared-resources"]`)); diff --git a/packages/fiori/src/BarcodeScannerDialog.ts b/packages/fiori/src/BarcodeScannerDialog.ts index 908b07e1efc0..3f51fbf9acdb 100644 --- a/packages/fiori/src/BarcodeScannerDialog.ts +++ b/packages/fiori/src/BarcodeScannerDialog.ts @@ -73,8 +73,8 @@ type BarcodeScannerDialogScanErrorEventDetail = { tag: "ui5-barcode-scanner-dialog", languageAware: true, renderer: litRender, - staticAreaTemplate: BarcodeScannerDialogTemplate, - staticAreaStyles: [BarcodeScannerDialogCss], + template: BarcodeScannerDialogTemplate, + styles: [BarcodeScannerDialogCss], dependencies: [ Dialog, BusyIndicator, @@ -204,18 +204,16 @@ class BarcodeScannerDialog extends UI5Element { return navigator.mediaDevices.getUserMedia(defaultMediaConstraints); } - async _getDialog() { - const staticAreaItem = await this.getStaticAreaItemDomRef(); - return staticAreaItem!.querySelector("[ui5-dialog]")!; + _getDialog() { + return this.shadowRoot!.querySelector("[ui5-dialog]")!; } - async _getVideoElement() { - const staticAreaItem = await this.getStaticAreaItemDomRef(); - return staticAreaItem!.querySelector(".ui5-barcode-scanner-dialog-video")!; + _getVideoElement() { + return this.shadowRoot!.querySelector(".ui5-barcode-scanner-dialog-video")!; } - async _showDialog() { - this.dialog = await this._getDialog(); + _showDialog() { + this.dialog = this._getDialog(); this.dialog.show(); this.open = true; } @@ -231,14 +229,14 @@ class BarcodeScannerDialog extends UI5Element { this._decodeFromCamera(); } - async _resetReader() { - const videoElement = await this._getVideoElement(); + _resetReader() { + const videoElement = this._getVideoElement(); videoElement.pause(); this._codeReader.reset(); } - async _decodeFromCamera() { - const videoElement = await this._getVideoElement(); + _decodeFromCamera() { + const videoElement = this._getVideoElement(); this._codeReader.decodeFromVideoDevice(null, videoElement, (result: Result, err?: Exception) => { this.loading = false; if (result) { diff --git a/packages/fiori/src/MediaGallery.ts b/packages/fiori/src/MediaGallery.ts index c10b8f3ec460..570c44e07c0f 100644 --- a/packages/fiori/src/MediaGallery.ts +++ b/packages/fiori/src/MediaGallery.ts @@ -91,7 +91,6 @@ const COLUMNS_COUNT: Record = { renderer: litRender, styles: [MediaGalleryCss], template: MediaGalleryTemplate, - staticAreaTemplate: MediaGalleryTemplate, dependencies: [ MediaGalleryItem, Button, diff --git a/packages/fiori/src/NotificationListGroupItem.hbs b/packages/fiori/src/NotificationListGroupItem.hbs index 916f187c6027..816f15bcf8a0 100644 --- a/packages/fiori/src/NotificationListGroupItem.hbs +++ b/packages/fiori/src/NotificationListGroupItem.hbs @@ -87,3 +87,5 @@ > {{/if}} + +{{>include "./NotificationOverflowActionsPopover.hbs"}} \ No newline at end of file diff --git a/packages/fiori/src/NotificationListGroupItem.ts b/packages/fiori/src/NotificationListGroupItem.ts index a9a477f8ee0d..b6380012ff56 100644 --- a/packages/fiori/src/NotificationListGroupItem.ts +++ b/packages/fiori/src/NotificationListGroupItem.ts @@ -37,6 +37,7 @@ import NotificationListGroupItemTemplate from "./generated/templates/Notificatio // Styles import NotificationListGroupItemCss from "./generated/themes/NotificationListGroupItem.css.js"; +import NotificationOverflowActionsPopoverCss from "./generated/themes/NotificationOverflowActionsPopover.css.js"; type NotificationListGroupItemToggleEventDetail = { item: NotificationListGroupItem, @@ -73,7 +74,10 @@ type NotificationListGroupItemToggleEventDetail = { @customElement({ tag: "ui5-li-notification-group", languageAware: true, - styles: NotificationListGroupItemCss, + styles: [ + NotificationListGroupItemCss, + NotificationOverflowActionsPopoverCss, + ], template: NotificationListGroupItemTemplate, dependencies: [ List, diff --git a/packages/fiori/src/NotificationListItem.hbs b/packages/fiori/src/NotificationListItem.hbs index 788bcf065e8b..919e6eb25950 100644 --- a/packages/fiori/src/NotificationListItem.hbs +++ b/packages/fiori/src/NotificationListItem.hbs @@ -102,3 +102,5 @@ > {{/if}} + +{{>include "./NotificationOverflowActionsPopover.hbs"}} \ No newline at end of file diff --git a/packages/fiori/src/NotificationListItem.ts b/packages/fiori/src/NotificationListItem.ts index 5c2da797a3cd..1dbe4d28b383 100644 --- a/packages/fiori/src/NotificationListItem.ts +++ b/packages/fiori/src/NotificationListItem.ts @@ -38,6 +38,7 @@ import NotificationListItemTemplate from "./generated/templates/NotificationList // Styles import NotificationListItemCss from "./generated/themes/NotificationListItem.css.js"; +import NotificationOverflowActionsPopoverCss from "./generated/themes/NotificationOverflowActionsPopover.css.js"; import type { NotificationListItemBaseCloseEventDetail as NotificationListItemCloseEventDetail } from "./NotificationListItemBase.js"; @@ -80,7 +81,10 @@ type Footnote = Record; @customElement({ tag: "ui5-li-notification", languageAware: true, - styles: NotificationListItemCss, + styles: [ + NotificationListItemCss, + NotificationOverflowActionsPopoverCss, + ], template: NotificationListItemTemplate, dependencies: [ Button, diff --git a/packages/fiori/src/NotificationListItemBase.ts b/packages/fiori/src/NotificationListItemBase.ts index ee877d740f3e..a802c90703be 100644 --- a/packages/fiori/src/NotificationListItemBase.ts +++ b/packages/fiori/src/NotificationListItemBase.ts @@ -19,12 +19,6 @@ import "@ui5/webcomponents-icons/dist/message-error.js"; import "@ui5/webcomponents-icons/dist/message-warning.js"; import "@ui5/webcomponents-icons/dist/overflow.js"; -// Templates -import NotificationOverflowActionsPopoverTemplate from "./generated/templates/NotificationOverflowActionsPopoverTemplate.lit.js"; - -// Styles -import NotificationOverflowActionsPopoverCss from "./generated/themes/NotificationOverflowActionsPopover.css.js"; - /** * Defines the icons corresponding to the notification's priority. */ @@ -48,10 +42,7 @@ type NotificationListItemBaseCloseEventDetail = { * @since 1.0.0-rc.8 * @public */ -@customElement({ - staticAreaStyles: NotificationOverflowActionsPopoverCss, - staticAreaTemplate: NotificationOverflowActionsPopoverTemplate, -}) +@customElement() /** * Fired when the `Close` button is pressed. @@ -217,19 +208,18 @@ class NotificationListItemBase extends ListItemBase { return this.actions.find(action => action._id === id); } - async openOverflow() { - const overflowPopover = await this.getOverflowPopover(); + openOverflow() { + const overflowPopover = this.getOverflowPopover(); overflowPopover.showAt(this.overflowButtonDOM); } - async closeOverflow() { - const overflowPopover = await this.getOverflowPopover(); + closeOverflow() { + const overflowPopover = this.getOverflowPopover(); overflowPopover.close(); } - async getOverflowPopover() { - const staticAreaItem = await this.getStaticAreaItemDomRef(); - return staticAreaItem!.querySelector(".ui5-notification-overflow-popover")!; + getOverflowPopover() { + return this.shadowRoot!.querySelector(".ui5-notification-overflow-popover")!; } static async onDefine() { diff --git a/packages/fiori/src/ShellBar.hbs b/packages/fiori/src/ShellBar.hbs index 9954cbb374ac..3796b2eaf322 100644 --- a/packages/fiori/src/ShellBar.hbs +++ b/packages/fiori/src/ShellBar.hbs @@ -233,3 +233,5 @@ {{/inline}} + +{{>include "./ShellBarPopover.hbs"}} \ No newline at end of file diff --git a/packages/fiori/src/ShellBar.ts b/packages/fiori/src/ShellBar.ts index 7e0ad09753de..ba6db7ef4c8a 100644 --- a/packages/fiori/src/ShellBar.ts +++ b/packages/fiori/src/ShellBar.ts @@ -1,4 +1,5 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; +import { renderFinished } from "@ui5/webcomponents-base/dist/Render.js"; import property from "@ui5/webcomponents-base/dist/decorators/property.js"; import slot from "@ui5/webcomponents-base/dist/decorators/slot.js"; import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js"; @@ -9,7 +10,6 @@ import { getFeature } from "@ui5/webcomponents-base/dist/FeaturesRegistry.js"; import AnimationMode from "@ui5/webcomponents-base/dist/types/AnimationMode.js"; import { getAnimationMode } from "@ui5/webcomponents-base/dist/config/AnimationMode.js"; import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js"; -import { renderFinished } from "@ui5/webcomponents-base/dist/Render.js"; import StandardListItem from "@ui5/webcomponents/dist/StandardListItem.js"; import List from "@ui5/webcomponents/dist/List.js"; import type { ListSelectionChangeEventDetail } from "@ui5/webcomponents/dist/List.js"; @@ -33,7 +33,6 @@ import type ShellBarItem from "./ShellBarItem.js"; // Templates import ShellBarTemplate from "./generated/templates/ShellBarTemplate.lit.js"; -import ShellBarPopoverTemplate from "./generated/templates/ShellBarPopoverTemplate.lit.js"; // Styles import shellBarStyles from "./generated/themes/ShellBar.css.js"; @@ -172,9 +171,7 @@ const HANDLE_RESIZE_DEBOUNCE_RATE = 200; // ms languageAware: true, renderer: litRender, template: ShellBarTemplate, - staticAreaTemplate: ShellBarPopoverTemplate, - styles: shellBarStyles, - staticAreaStyles: [ShellBarPopoverCss], + styles: [shellBarStyles, ShellBarPopoverCss], dependencies: [ Button, List, @@ -426,7 +423,7 @@ class ShellBar extends UI5Element { _itemsInfo!: Array; @property({ type: Object, multiple: true }) - _menuPopoverItems!: Array; + _menuPopoverItems: Array; @property({ type: Boolean, noAttribute: true }) _menuPopoverExpanded!: boolean; @@ -518,9 +515,9 @@ class ShellBar extends UI5Element { coPilot?: ShellBarCoPilot; _coPilotIcon: string; _debounceInterval?: Timeout | null; - _hiddenIcons?: Array; + _hiddenIcons: Array; _handleResize: ResizeObserverCallback; - _headerPress: () => Promise; + _headerPress: () => void; static get CO_PILOT_ICON_PRESSED() { return "sap-icon://da-2"; @@ -553,6 +550,8 @@ class ShellBar extends UI5Element { constructor() { super(); + this._menuPopoverItems = []; + this._hiddenIcons = []; this._itemsInfo = []; this._isInitialRendering = true; this._coPilotIcon = ShellBar.CO_PILOT_ICON_UNPRESSED; @@ -564,19 +563,20 @@ class ShellBar extends UI5Element { this._updateClonedMenuItems(); }); - this._headerPress = async () => { + this._headerPress = () => { this._updateClonedMenuItems(); if (this.hasMenuItems) { - const menuPopover = await this._getMenuPopover(); - menuPopover!.showAt(this.shadowRoot!.querySelector