diff --git a/package.json b/package.json index 0ef44bd95d9f..630c3fb564b1 100644 --- a/package.json +++ b/package.json @@ -27,12 +27,18 @@ "clean:fiori": "cd packages/fiori && yarn clean", "prepare:main": "cd packages/main && nps prepare", "prepare:fiori": "cd packages/fiori && nps prepare", + "scopePrepare:main": "cd packages/main && nps scope.prepare", + "scopePrepare:fiori": "cd packages/fiori && nps scope.prepare", "dev:base": "cd packages/base && nps watch", "dev:localization": "cd packages/localization && nps watch", "dev:main": "cd packages/main && nps dev", "dev:fiori": "cd packages/fiori && nps dev", + "scopeDev:main": "cd packages/main && nps scope.dev", + "scopeDev:fiori": "cd packages/fiori && nps scope.dev", "start": "npm-run-all --sequential build:base build:localization build:theme-base build:icons prepare:main prepare:fiori start:all", + "startWithScope": "npm-run-all --sequential build:base build:localization build:theme-base build:icons scopePrepare:main scopePrepare:fiori scopeStart:all", "start:all": "npm-run-all --parallel dev:base dev:localization dev:main dev:fiori", + "scopeStart:all": "npm-run-all --parallel dev:base dev:localization scopeDev:main scopeDev:fiori", "start:base": "cd packages/base && yarn start", "start:main": "cd packages/main && yarn start", "start:fiori": "cd packages/fiori && yarn start", diff --git a/packages/base/src/CustomElementsScope.js b/packages/base/src/CustomElementsScope.js new file mode 100644 index 000000000000..75d4946ca1be --- /dev/null +++ b/packages/base/src/CustomElementsScope.js @@ -0,0 +1,108 @@ +let suf; +let rulesObj = { + include: [/^ui5-/], + exclude: [], +}; +const tagsCache = new Map(); // true/false means the tag should/should not be cached, undefined means not known yet. + +/** + * Sets the suffix to be used for custom elements scoping, f.e. pass "demo" to get tags such as "ui5-button-demo". + * Note: by default all tags starting with "ui5-" will be scoped, unless you change this by calling "setCustomElementsScopingRules" + * + * @public + * @param suffix The scoping suffix + */ +const setCustomElementsScopingSuffix = suffix => { + if (!suffix.match(/^[a-zA-Z0-9_-]+$/)) { + throw new Error("Only alphanumeric characters and dashes allowed for the scoping suffix"); + } + + suf = suffix; +}; + +/** + * Returns the currently set scoping suffix, or undefined if not set. + * + * @public + * @returns {String|undefined} + */ +const getCustomElementsScopingSuffix = () => { + return suf; +}; + +/** + * Sets the rules, governing which custom element tags to scope and which not, f.e. + * setCustomElementsScopingRules({include: [/^ui5-/]}, exclude: [/^ui5-mylib-/, /^ui5-carousel$/]); + * will scope all elements starting with "ui5-" but not the ones starting with "ui5-mylib-" and not "ui5-carousel". + * + * @public + * @param rules Object with "include" and "exclude" properties, both arrays of regular expressions. Note that "include" + * rules are applied first and "exclude" rules second. + */ +const setCustomElementsScopingRules = rules => { + if (!rules || !rules.include) { + throw new Error(`"rules" must be an object with at least an "include" property`); + } + + if (!Array.isArray(rules.include) || rules.include.some(rule => !(rule instanceof RegExp))) { + throw new Error(`"rules.include" must be an array of regular expressions`); + } + + if (rules.exclude && (!Array.isArray(rules.exclude) || rules.exclude.some(rule => !(rule instanceof RegExp)))) { + throw new Error(`"rules.exclude" must be an array of regular expressions`); + } + + rules.exclude = rules.exclude || []; + rulesObj = rules; + tagsCache.clear(); // reset the cache upon setting new rules +}; + +/** + * Returns the rules, governing which custom element tags to scope and which not. By default, all elements + * starting with "ui5-" are scoped. The default rules are: {include: [/^ui5-/]}. + * + * @public + * @returns {Object} + */ +const getCustomElementsScopingRules = () => { + return rulesObj; +}; + +/** + * Determines whether custom elements with the given tag should be scoped or not. + * The tag is first matched against the "include" rules and then against the "exclude" rules and the + * result is cached until new rules are set. + * + * @public + * @param tag + */ +const shouldScopeCustomElement = tag => { + if (!tagsCache.has(tag)) { + const result = rulesObj.include.some(rule => tag.match(rule)) && !rulesObj.exclude.some(rule => tag.match(rule)); + tagsCache.set(tag, result); + } + + return tagsCache.get(tag); +}; + +/** + * Returns the currently set scoping suffix, if any and if the tag should be scoped, or undefined otherwise. + * + * @public + * @param tag + * @returns {String} + */ +const getEffectiveScopingSuffixForTag = tag => { + if (shouldScopeCustomElement(tag)) { + return getCustomElementsScopingSuffix(); + } +}; + +export { + setCustomElementsScopingSuffix, + getCustomElementsScopingSuffix, + setCustomElementsScopingRules, + getCustomElementsScopingRules, + shouldScopeCustomElement, + getEffectiveScopingSuffixForTag, +}; diff --git a/packages/base/src/StaticAreaItem.js b/packages/base/src/StaticAreaItem.js index 2bf751ed1ddf..b4b669a70d02 100644 --- a/packages/base/src/StaticAreaItem.js +++ b/packages/base/src/StaticAreaItem.js @@ -1,6 +1,7 @@ import { getStaticAreaInstance, removeStaticArea } from "./StaticArea.js"; import RenderScheduler from "./RenderScheduler.js"; import getStylesString from "./theming/getStylesString.js"; +import executeTemplate from "./renderer/executeTemplate.js"; /** * @class @@ -22,7 +23,7 @@ class StaticAreaItem { * @protected */ _updateFragment() { - const renderResult = this.ui5ElementContext.constructor.staticAreaTemplate(this.ui5ElementContext), + const renderResult = executeTemplate(this.ui5ElementContext.constructor.staticAreaTemplate, this.ui5ElementContext), stylesToAdd = window.ShadyDOM ? false : getStylesString(this.ui5ElementContext.constructor.staticAreaStyles); if (!this.staticAreaItemDomRef) { diff --git a/packages/base/src/UI5Element.js b/packages/base/src/UI5Element.js index 855800463b54..4431a7af3d5e 100644 --- a/packages/base/src/UI5Element.js +++ b/packages/base/src/UI5Element.js @@ -1,6 +1,7 @@ import merge from "./thirdparty/merge.js"; import boot from "./boot.js"; import UI5ElementMetadata from "./UI5ElementMetadata.js"; +import executeTemplate from "./renderer/executeTemplate.js"; import StaticAreaItem from "./StaticAreaItem.js"; import RenderScheduler from "./RenderScheduler.js"; import { registerTag, isTagRegistered, recordTagRegistrationFailure } from "./CustomElementsRegistry.js"; @@ -26,6 +27,7 @@ const metadata = { let autoId = 0; const elementTimeouts = new Map(); +const uniqueDependenciesCache = new Map(); const GLOBAL_CONTENT_DENSITY_CSS_VAR = "--_ui5_content_density"; const GLOBAL_DIR_CSS_VAR = "--_ui5_dir"; @@ -98,6 +100,8 @@ class UI5Element extends HTMLElement { * @private */ async connectedCallback() { + this.setAttribute(this.constructor.getMetadata().getPureTag(), ""); + const needsShadowDOM = this.constructor._needsShadowDOM(); const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged(); @@ -549,7 +553,7 @@ class UI5Element extends HTMLElement { } let styleToPrepend; - const renderResult = this.constructor.template(this); + const renderResult = executeTemplate(this.constructor.template, this); // IE11, Edge if (window.ShadyDOM) { @@ -968,6 +972,50 @@ class UI5Element extends HTMLElement { 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) + * - slotted components that the component may need to communicate with + * + * @protected + */ + static get dependencies() { + return []; + } + + /** + * Returns a list of the unique dependencies for this UI5 Web Component + * + * @public + */ + static getUniqueDependencies() { + if (!uniqueDependenciesCache.has(this)) { + const filtered = this.dependencies.filter((dep, index, deps) => deps.indexOf(dep) === index); + uniqueDependenciesCache.set(this, filtered); + } + + return uniqueDependenciesCache.get(this); + } + + /** + * Returns a promise that resolves whenever all dependencies for this UI5 Web Component have resolved + * + * @returns {Promise} + */ + static whenDependenciesDefined() { + return Promise.all(this.getUniqueDependencies().map(dep => dep.define())); + } + + /** + * Hook that will be called upon custom element definition + * + * @protected + * @returns {Promise} + */ + static async onDefine() { + return Promise.resolve(); + } + /** * Registers a UI5 Web Component in the browser window object * @public @@ -976,9 +1024,10 @@ class UI5Element extends HTMLElement { static async define() { await boot(); - if (this.onDefine) { - await this.onDefine(); - } + await Promise.all([ + this.whenDependenciesDefined(), + this.onDefine(), + ]); const tag = this.getMetadata().getTag(); const altTag = this.getMetadata().getAltTag(); diff --git a/packages/base/src/UI5ElementMetadata.js b/packages/base/src/UI5ElementMetadata.js index 437369ae539b..09d2c8b716de 100644 --- a/packages/base/src/UI5ElementMetadata.js +++ b/packages/base/src/UI5ElementMetadata.js @@ -2,6 +2,7 @@ import DataType from "./types/DataType.js"; import isDescendantOf from "./util/isDescendantOf.js"; import { camelToKebabCase } from "./util/StringHelper.js"; import isSlot from "./util/isSlot.js"; +import { getEffectiveScopingSuffixForTag } from "./CustomElementsScope.js"; /** * @@ -33,12 +34,26 @@ class UI5ElementMetadata { return validateSingleSlot(value, slotData); } + /** + * Returns the tag of the UI5 Element without the scope + * @public + */ + getPureTag() { + return this.metadata.tag; + } + /** * Returns the tag of the UI5 Element * @public */ getTag() { - return this.metadata.tag; + const pureTag = this.metadata.tag; + const suffix = getEffectiveScopingSuffixForTag(pureTag); + if (!suffix) { + return pureTag; + } + + return `${pureTag}-${suffix}`; } /** @@ -46,7 +61,17 @@ class UI5ElementMetadata { * @public */ getAltTag() { - return this.metadata.altTag; + const pureAltTag = this.metadata.altTag; + if (!pureAltTag) { + return; + } + + const suffix = getEffectiveScopingSuffixForTag(pureAltTag); + if (!suffix) { + return pureAltTag; + } + + return `${pureAltTag}-${suffix}`; } /** diff --git a/packages/base/src/renderer/LitRenderer.js b/packages/base/src/renderer/LitRenderer.js index 3461aa1a37d2..8817c603a56d 100644 --- a/packages/base/src/renderer/LitRenderer.js +++ b/packages/base/src/renderer/LitRenderer.js @@ -1,4 +1,15 @@ -import { html, render } from "lit-html/lit-html.js"; +import { html, svg, render } from "lit-html/lit-html.js"; +import scopeHTML from "./scopeHTML.js"; + +let tags; +let suffix; + +const setTags = t => { + tags = t; +}; +const setSuffix = s => { + suffix = s; +}; const litRender = (templateResult, domNode, styles, { eventContext } = {}) => { if (styles) { @@ -7,7 +18,11 @@ const litRender = (templateResult, domNode, styles, { eventContext } = {}) => { render(templateResult, domNode, { eventContext }); }; -export { html, svg } from "lit-html/lit-html.js"; +const scopedHtml = (strings, ...values) => html(scopeHTML(strings, tags, suffix), ...values); +const scopedSvg = (strings, ...values) => svg(scopeHTML(strings, tags, suffix), ...values); + +export { setTags, setSuffix }; +export { scopedHtml as html, scopedSvg as svg }; export { repeat } from "lit-html/directives/repeat.js"; export { classMap } from "lit-html/directives/class-map.js"; export { styleMap } from "lit-html/directives/style-map.js"; diff --git a/packages/base/src/renderer/executeTemplate.js b/packages/base/src/renderer/executeTemplate.js new file mode 100644 index 000000000000..b316546fd95e --- /dev/null +++ b/packages/base/src/renderer/executeTemplate.js @@ -0,0 +1,17 @@ +import { getCustomElementsScopingSuffix, shouldScopeCustomElement } from "../CustomElementsScope.js"; + +/** + * Runs a component's template with the component's current state, while also scoping HTML + * + * @param template - the template to execute + * @param component - the component + * @public + * @returns {*} + */ +const executeTemplate = (template, component) => { + const tagsToScope = component.constructor.getUniqueDependencies().map(dep => dep.getMetadata().getPureTag()).filter(shouldScopeCustomElement); + const scope = getCustomElementsScopingSuffix(); + return template(component, tagsToScope, scope); +}; + +export default executeTemplate; diff --git a/packages/base/src/renderer/scopeHTML.js b/packages/base/src/renderer/scopeHTML.js new file mode 100644 index 000000000000..2125e693e482 --- /dev/null +++ b/packages/base/src/renderer/scopeHTML.js @@ -0,0 +1,32 @@ +const cache = new Map(); + +const scopeHTML = (strings, tags, suffix) => { + if (suffix && tags && tags.length) { + strings = strings.map(string => { + if (cache.has(string)) { + return cache.get(string); + } + + /* + const allTags = [...string.matchAll(/<(ui5-.*?)[> ]/g)].map(x => x[1]); + allTags.forEach(t => { + if (!tags.includes(t)) { + throw new Error(`${t} not found in ${string}`); + // console.log(t, " in ", string); + } + }); + */ + + let result = string; + tags.forEach(tag => { + result = result.replace(new RegExp(`( \t\n])`, "g"), `$1$2-${suffix}$3`); + }); + cache.set(string, result); + return result; + }); + } + + return strings; +}; + +export default scopeHTML; diff --git a/packages/base/src/theming/adaptCSSForIE.js b/packages/base/src/theming/adaptCSSForIE.js index ba00ee91c847..b000e6af7bac 100644 --- a/packages/base/src/theming/adaptCSSForIE.js +++ b/packages/base/src/theming/adaptCSSForIE.js @@ -44,7 +44,7 @@ const replaceSelectors = (str, selector, replacement) => { return str; }; -const adaptLinePart = (line, tag) => { +const adaptLinePart = (line, tag, pureTag) => { line = line.trim(); line = replaceSelectors(line, "::slotted", ``); // first remove all ::slotted() occurrences @@ -59,16 +59,21 @@ const adaptLinePart = (line, tag) => { return line; } - // IE specific selector (directly written with the tag) - keep it + // IE specific selector (directly written with the tag, f.e. ui5-button {}) - keep it if (line.match(new RegExp(`^${tag}[^a-zA-Z0-9-]`))) { return line; } + // IE specific selector (directly written with the tag attribute, f.e. [ui5-button] {}) - keep it + if (pureTag && line.startsWith(`[${pureTag}]`)) { + return line; + } + // No host and no tag in the beginning of the selector - prepend the tag return `${tag} ${line}`; }; -const adaptCSSForIE = (str, tag) => { +const adaptCSSForIE = (str, tag, pureTag) => { str = str.replace(/\n/g, ` `); str = str.replace(/([{}])/g, `$1\n`); let result = ``; @@ -78,7 +83,7 @@ const adaptCSSForIE = (str, tag) => { if (mustProcess) { const lineParts = line.split(","); const processedLineParts = lineParts.map(linePart => { - return adaptLinePart(linePart, tag); + return adaptLinePart(linePart, tag, pureTag); }); line = processedLineParts.join(","); } diff --git a/packages/base/src/theming/createComponentStyleTag.js b/packages/base/src/theming/createComponentStyleTag.js index 3267d871d70d..66163b0460fa 100644 --- a/packages/base/src/theming/createComponentStyleTag.js +++ b/packages/base/src/theming/createComponentStyleTag.js @@ -26,12 +26,13 @@ const getStaticStyle = ElementClass => { */ const createComponentStyleTag = ElementClass => { const tag = ElementClass.getMetadata().getTag(); + const pureTag = ElementClass.getMetadata().getPureTag(); if (IEStyleSet.has(tag)) { return; } let cssContent = getEffectiveStyle(ElementClass); - cssContent = adaptCSSForIE(cssContent, tag); + cssContent = adaptCSSForIE(cssContent, tag, pureTag); // Append static CSS, if any, for IE let staticCssContent = getStaticStyle(ElementClass); diff --git a/packages/fiori/.eslintignore b/packages/fiori/.eslintignore index dd6ae07aba35..76710c01592f 100644 --- a/packages/fiori/.eslintignore +++ b/packages/fiori/.eslintignore @@ -3,8 +3,7 @@ target dist lib test -bundle.esm.js -bundle.es5.js +bundle.*.js rollup.config*.js wdio.conf.js postcss.config.js diff --git a/packages/fiori/bundle.es5.js b/packages/fiori/bundle.es5.js index 0ce8e2d288e4..788dda545ff1 100644 --- a/packages/fiori/bundle.es5.js +++ b/packages/fiori/bundle.es5.js @@ -1,21 +1,6 @@ // ES5 bundle targets IE11 only import "@ui5/webcomponents-base/dist/features/browsersupport/IE11.js"; -import "./bundle.esm.js"; +import testAssets from "./bundle.esm.js"; -import { getAnimationMode } from "@ui5/webcomponents-base/dist/config/AnimationMode.js"; -import { getTheme, setTheme } from "@ui5/webcomponents-base/dist/config/Theme.js"; -import { setNoConflict } from "@ui5/webcomponents-base/dist/config/NoConflict.js"; -import { getRTL } from "@ui5/webcomponents-base/dist/config/RTL.js"; -import { getRegisteredNames as getIconNames } from "@ui5/webcomponents-base/dist/SVGIconRegistry.js" -const configuration = { - getAnimationMode, - getTheme, - setTheme, - setNoConflict, - getRTL, -}; -export { - configuration, - getIconNames, -}; +export default testAssets; diff --git a/packages/fiori/bundle.esm.js b/packages/fiori/bundle.esm.js index e1258153f5f6..6ffe5d349002 100644 --- a/packages/fiori/bundle.esm.js +++ b/packages/fiori/bundle.esm.js @@ -1,4 +1,4 @@ -import "@ui5/webcomponents/bundle.esm.js"; +import testAssets from "@ui5/webcomponents/bundle.esm.js"; // FIORI assets import "./dist/Assets.js"; @@ -19,4 +19,6 @@ import UploadCollection from "./dist/UploadCollection.js"; import UploadCollectionItem from "./dist/UploadCollectionItem.js"; import NotificationListItem from "./dist/NotificationListItem.js" import NotificationListGroupItem from "./dist/NotificationListGroupItem.js"; -import NotificationOverflowAction from "./dist/NotificationOverflowAction.js"; \ No newline at end of file +import NotificationOverflowAction from "./dist/NotificationOverflowAction.js"; + +export default testAssets; diff --git a/packages/fiori/bundle.scoped.es5.js b/packages/fiori/bundle.scoped.es5.js new file mode 100644 index 000000000000..8f60488d88a6 --- /dev/null +++ b/packages/fiori/bundle.scoped.es5.js @@ -0,0 +1,6 @@ +// ES5 bundle targets IE11 only +import "@ui5/webcomponents-base/dist/features/browsersupport/IE11.js"; + +import testAssets from "./bundle.scoped.esm.js"; + +export default testAssets; diff --git a/packages/fiori/bundle.scoped.esm.js b/packages/fiori/bundle.scoped.esm.js new file mode 100644 index 000000000000..f2aeb75a1a37 --- /dev/null +++ b/packages/fiori/bundle.scoped.esm.js @@ -0,0 +1,5 @@ +import testAssets from "@ui5/webcomponents/bundle.scoped.esm.js"; + +import "./bundle.esm.js"; + +export default testAssets; diff --git a/packages/fiori/package.json b/packages/fiori/package.json index 282c3441f118..a8f0a6cfddec 100644 --- a/packages/fiori/package.json +++ b/packages/fiori/package.json @@ -2,6 +2,9 @@ "name": "@ui5/webcomponents-fiori", "version": "1.0.0-rc.8", "description": "UI5 Web Components: webcomponents.fiori", + "ui5": { + "webComponentsPackage": true + }, "author": "SAP SE (https://www.sap.com)", "license": "Apache-2.0", "private": false, diff --git a/packages/fiori/src/FlexibleColumnLayout.js b/packages/fiori/src/FlexibleColumnLayout.js index 194c838c08b3..e878b359491b 100644 --- a/packages/fiori/src/FlexibleColumnLayout.js +++ b/packages/fiori/src/FlexibleColumnLayout.js @@ -245,11 +245,12 @@ class FlexibleColumnLayout extends UI5Element { return FlexibleColumnLayoutTemplate; } + static get dependencies() { + return [Button]; + } + static async onDefine() { - await Promise.all([ - Button.define(), - fetchI18nBundle("@ui5/webcomponents-fiori"), - ]); + await fetchI18nBundle("@ui5/webcomponents-fiori"); } static get BREAKPOINTS() { diff --git a/packages/fiori/src/NotificationListGroupItem.js b/packages/fiori/src/NotificationListGroupItem.js index 55b57882a75f..4091577824f9 100644 --- a/packages/fiori/src/NotificationListGroupItem.js +++ b/packages/fiori/src/NotificationListGroupItem.js @@ -143,15 +143,18 @@ class NotificationListGroupItem extends NotificationListItemBase { }); } + static get dependencies() { + return [ + List, + Button, + Icon, + BusyIndicator, + Popover, + ]; + } + static async onDefine() { - await Promise.all([ - List.define(), - Button.define(), - Icon.define(), - BusyIndicator.define(), - Popover.define(), - fetchI18nBundle("@ui5/webcomponents-fiori"), - ]); + await fetchI18nBundle("@ui5/webcomponents-fiori"); } get itemsCount() { diff --git a/packages/fiori/src/NotificationListItem.js b/packages/fiori/src/NotificationListItem.js index 79ff0d13906c..9b03fb5d5f29 100644 --- a/packages/fiori/src/NotificationListItem.js +++ b/packages/fiori/src/NotificationListItem.js @@ -197,15 +197,18 @@ class NotificationListItem extends NotificationListItemBase { return NotificationListItemTemplate; } + static get dependencies() { + return [ + Button, + Icon, + BusyIndicator, + Link, + Popover, + ]; + } + static async onDefine() { - await Promise.all([ - Button.define(), - Icon.define(), - BusyIndicator.define(), - Link.define(), - Popover.define(), - fetchI18nBundle("@ui5/webcomponents-fiori"), - ]); + await fetchI18nBundle("@ui5/webcomponents-fiori"); } onEnterDOM() { diff --git a/packages/fiori/src/ProductSwitchItem.js b/packages/fiori/src/ProductSwitchItem.js index b3b7e7f9c9a1..0d439e775ec8 100644 --- a/packages/fiori/src/ProductSwitchItem.js +++ b/packages/fiori/src/ProductSwitchItem.js @@ -215,8 +215,8 @@ class ProductSwitchItem extends UI5Element { this.fireEvent("click", { item: this }); } - static async onDefine() { - await Icon.define(); + static get dependencies() { + return [Icon]; } } diff --git a/packages/fiori/src/ShellBar.js b/packages/fiori/src/ShellBar.js index bd30a1d9a5c6..193b73523f91 100644 --- a/packages/fiori/src/ShellBar.js +++ b/packages/fiori/src/ShellBar.js @@ -1021,14 +1021,17 @@ class ShellBar extends UI5Element { }; } + static get dependencies() { + return [ + Button, + List, + Popover, + StandardListItem, + ]; + } + static async onDefine() { - await Promise.all([ - fetchI18nBundle("@ui5/webcomponents-fiori"), - Button.define(), - List.define(), - Popover.define(), - StandardListItem.define(), - ]); + await fetchI18nBundle("@ui5/webcomponents-fiori"); } } diff --git a/packages/fiori/src/SideNavigation.js b/packages/fiori/src/SideNavigation.js index 6108dc8ab2aa..646671821d51 100644 --- a/packages/fiori/src/SideNavigation.js +++ b/packages/fiori/src/SideNavigation.js @@ -1,7 +1,10 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; import ResponsivePopover from "@ui5/webcomponents/dist/ResponsivePopover.js"; +import List from "@ui5/webcomponents/dist/List.js"; +import StandardListItem from "@ui5/webcomponents/dist/StandardListItem.js"; import Tree from "@ui5/webcomponents/dist/Tree.js"; +import TreeItem from "@ui5/webcomponents/dist/TreeItem.js"; import SideNavigationTemplate from "./generated/templates/SideNavigationTemplate.lit.js"; import SideNavigationItemPopoverContentTemplate from "./generated/templates/SideNavigationItemPopoverContentTemplate.lit.js"; @@ -132,11 +135,14 @@ class SideNavigation extends UI5Element { return SideNavigationItemPopoverContentTemplate; } - static async onDefine() { - await Promise.all([ - Tree.define(), - ResponsivePopover.define(), - ]); + static get dependencies() { + return [ + List, + StandardListItem, + Tree, + TreeItem, + ResponsivePopover, + ]; } onBeforeRendering() { @@ -202,7 +208,7 @@ class SideNavigation extends UI5Element { } async getPicker() { - return (await this.getStaticAreaItemDomRef()).querySelector("ui5-responsive-popover"); + return (await this.getStaticAreaItemDomRef()).querySelector("[ui5-responsive-popover]"); } async openPicker(opener) { diff --git a/packages/fiori/src/UploadCollection.js b/packages/fiori/src/UploadCollection.js index e062b19dca02..8e50ef70cc08 100644 --- a/packages/fiori/src/UploadCollection.js +++ b/packages/fiori/src/UploadCollection.js @@ -194,14 +194,17 @@ class UploadCollection extends UI5Element { return UploadCollectionTemplate; } + static get dependencies() { + return [ + Icon, + Label, + List, + Title, + ]; + } + static async onDefine() { - await Promise.all([ - Icon.define(), - Label.define(), - List.define(), - Title.define(), - fetchI18nBundle("@ui5/webcomponents-fiori"), - ]); + await fetchI18nBundle("@ui5/webcomponents-fiori"); } constructor() { diff --git a/packages/fiori/src/UploadCollectionItem.js b/packages/fiori/src/UploadCollectionItem.js index 3f7b16403643..6eb1839cf106 100644 --- a/packages/fiori/src/UploadCollectionItem.js +++ b/packages/fiori/src/UploadCollectionItem.js @@ -249,15 +249,19 @@ class UploadCollectionItem extends ListItem { return UploadCollectionItemTemplate; } + static get dependencies() { + return [ + ...ListItem.dependencies, + Button, + Input, + Link, + Label, + ProgressIndicator, + ]; + } + static async onDefine() { - await Promise.all([ - Button.define(), - Input.define(), - Link.define(), - Label.define(), - ProgressIndicator.define(), - fetchI18nBundle("@ui5/webcomponents-fiori"), - ]); + await fetchI18nBundle("@ui5/webcomponents-fiori"); } constructor() { diff --git a/packages/fiori/src/themes/ProductSwitchItem.css b/packages/fiori/src/themes/ProductSwitchItem.css index 37799da23372..816f07066119 100644 --- a/packages/fiori/src/themes/ProductSwitchItem.css +++ b/packages/fiori/src/themes/ProductSwitchItem.css @@ -134,12 +134,12 @@ } } -ui5-product-switch-item[focused] { +[ui5-product-switch-item][focused] { outline: none; position: relative; } -ui5-product-switch-item[focused] .ui5-product-switch-item-root::after { +[ui5-product-switch-item][focused] .ui5-product-switch-item-root::after { content: ""; position: absolute; border-color: var(--_ui5_product_switch_item_outline_color); @@ -151,6 +151,6 @@ ui5-product-switch-item[focused] .ui5-product-switch-item-root::after { right: var(--_ui5_product_switch_item_outline_offset_positive); } -ui5-product-switch-item[active][focused] .ui5-product-switch-item-root::after { +[ui5-product-switch-item][active][focused] .ui5-product-switch-item-root::after { border-color: var(--_ui5_product_switch_item_active_outline_color); -} \ No newline at end of file +} diff --git a/packages/fiori/src/themes/ShellBar.css b/packages/fiori/src/themes/ShellBar.css index 77212257e449..0b844847519e 100644 --- a/packages/fiori/src/themes/ShellBar.css +++ b/packages/fiori/src/themes/ShellBar.css @@ -19,7 +19,7 @@ .ui5-shellbar-menu-button, .ui5-shellbar-button, .ui5-shellbar-image-button, -::slotted(ui5-button[slot="startButton"]) { +::slotted([ui5-button][slot="startButton"]) { height: 2.25rem; padding: 0; margin-left: 0.5rem; @@ -40,18 +40,18 @@ .ui5-shellbar-menu-button, .ui5-shellbar-button, -::slotted(ui5-button[slot="startButton"]) { +::slotted([ui5-button][slot="startButton"]) { outline: none; } -::slotted(ui5-button[slot="startButton"]:hover), +::slotted([ui5-button][slot="startButton"]:hover), .ui5-shellbar-menu-button.ui5-shellbar-menu-button--interactive:hover, .ui5-shellbar-button:hover, .ui5-shellbar-image-button:hover { background: var(--sapShell_Hover_Background); } -::slotted(ui5-button[slot="startButton"][active]), +::slotted([ui5-button][slot="startButton"][active]), .ui5-shellbar-menu-button.ui5-shellbar-menu-button--interactive:active, .ui5-shellbar-button[active], .ui5-shellbar-image-button:active { @@ -59,7 +59,7 @@ color: var(--sapShell_Active_TextColor); } -::slotted(ui5-button[slot="startButton"][focused])::after, +::slotted([ui5-button][slot="startButton"][focused])::after, .ui5-shellbar-menu-button.ui5-shellbar-menu-button--interactive:focus::after, .ui5-shellbar-button[focused]::after, .ui5-shellbar-image-button:focus::after { @@ -78,7 +78,7 @@ slot[name="profile"] { min-width: 0; } -::slotted(ui5-avatar[slot="profile"]) { +::slotted([ui5-avatar][slot="profile"]) { min-width: 0; width: 2rem; height: 2rem; @@ -170,7 +170,7 @@ slot[name="profile"] { padding: 0.25rem 1rem; } -:host([breakpoint-size="S"]) ::slotted(ui5-button[slot="startButton"]) { +:host([breakpoint-size="S"]) ::slotted([ui5-button][slot="startButton"]) { margin-right: 0; } @@ -365,14 +365,14 @@ slot[name="profile"] { height: 2.25rem; } -::slotted(ui5-input) { +::slotted([ui5-input]) { background-color: var(--sapShellColor); border: 1px solid var(--sapShell_InteractiveBorderColor); color: var(--sapShell_TextColor); height: 100%; } -::slotted(ui5-input[focused]) { +::slotted([ui5-input][focused]) { outline: 1px dotted var(--sapContent_ContrastFocusColor); } @@ -384,18 +384,18 @@ slot[name="profile"] { /** * IE styles */ -ui5-input[value-state]:not([readonly]) { +[ui5-input][value-state]:not([readonly]) { background: var(--sapShellColor); border: 1px solid var(--sapShell_InteractiveBorderColor); } -ui5-input[value-state]:not([readonly]):hover, -ui5-input:not([value-state]):not([readonly]):hover { +[ui5-input][value-state]:not([readonly]):hover, +[ui5-input]:not([value-state]):not([readonly]):hover { background: var(--sapShell_Hover_Background); border: 1px solid var(--sapShell_InteractiveBorderColor); } -ui5-input[value-state]:not([value-state="None"])[focused] { +[ui5-input][value-state]:not([value-state="None"])[focused] { outline: 1px dotted var(--sapContent_ContrastFocusColor); } /* IE styles end */ @@ -436,7 +436,7 @@ ui5-input[value-state]:not([value-state="None"])[focused] { fill: var(--sapShellColor); } -:host [dir="rtl"] ::slotted(ui5-button[slot="startButton"]) { +:host [dir="rtl"] ::slotted([ui5-button][slot="startButton"]) { margin-left: 0.5rem; margin-right: 0; } @@ -464,13 +464,13 @@ ui5-input[value-state]:not([value-state="None"])[focused] { margin-right: 0; } -::slotted(ui5-button[slot="startButton"]) { +::slotted([ui5-button][slot="startButton"]) { margin-right: 0.5rem; margin-left: 0; justify-content: center; align-items: center; } -::slotted(ui5-button[profile-btn]) { +::slotted([ui5-button][profile-btn]) { width: auto; } diff --git a/packages/fiori/src/themes/UploadCollection.css b/packages/fiori/src/themes/UploadCollection.css index 0cc4acd7a20f..738ce997b19d 100644 --- a/packages/fiori/src/themes/UploadCollection.css +++ b/packages/fiori/src/themes/UploadCollection.css @@ -37,7 +37,7 @@ height: 8rem; } -.uc-no-files .icon-container ui5-icon { +.uc-no-files .icon-container [ui5-icon] { font-size: 6rem; width: 6rem; height: 6rem; @@ -45,7 +45,7 @@ opacity: 0.5; } -.uc-no-files ui5-title { +.uc-no-files [ui5-title] { font-size: var(--ui5_upload_collection_level_2Size); color: var(--sapGroup_TitleTextColor); margin: 1rem 0; @@ -102,7 +102,7 @@ opacity: 0.05; } -.uc-dnd-overlay ui5-icon { +.uc-dnd-overlay [ui5-icon] { width: 4rem; height: 4rem; margin-bottom: 1rem; @@ -115,13 +115,13 @@ color: var(--sapContent_NonInteractiveIconColor); } -.uc-dnd-overlay ui5-icon, +.uc-dnd-overlay [ui5-icon], .uc-dnd-overlay .dnd-overlay-text { z-index: 1; pointer-events: none; } -.uc-drop-overlay ui5-icon, +.uc-drop-overlay [ui5-icon], .uc-drop-overlay .dnd-overlay-text { color: var(--sapContent_DragAndDropActiveColor); } diff --git a/packages/fiori/src/themes/UploadCollectionItem.css b/packages/fiori/src/themes/UploadCollectionItem.css index 8a8b5107ece2..576ccb4e7e1b 100644 --- a/packages/fiori/src/themes/UploadCollectionItem.css +++ b/packages/fiori/src/themes/UploadCollectionItem.css @@ -17,7 +17,7 @@ margin-right: 0.75rem; } -::slotted(ui5-icon[slot="thumbnail"]) { +::slotted([ui5-icon][slot="thumbnail"]) { width: 3rem; height: 3rem; font-size: 2.5rem; @@ -28,7 +28,7 @@ height: 3rem; } -:host([actionable]) ::slotted(ui5-icon[slot="thumbnail"]) { +:host([actionable]) ::slotted([ui5-icon][slot="thumbnail"]) { color: var(--sapContent_IconColor); } @@ -60,7 +60,7 @@ white-space: pre-wrap; } -ui5-link.ui5-uci-file-name { +[ui5-link].ui5-uci-file-name { pointer-events: all; } @@ -73,7 +73,7 @@ ui5-link.ui5-uci-file-name { } /* Edit mode */ -.ui5-uci-edit-container ui5-input { +.ui5-uci-edit-container [ui5-input] { width: 60%; pointer-events: all; min-width: auto; @@ -153,4 +153,4 @@ ui5-link.ui5-uci-file-name { .ui5-uci-progress-labels { display: flex; justify-content: space-between; -} \ No newline at end of file +} diff --git a/packages/main/.eslintignore b/packages/main/.eslintignore index dd6ae07aba35..76710c01592f 100644 --- a/packages/main/.eslintignore +++ b/packages/main/.eslintignore @@ -3,8 +3,7 @@ target dist lib test -bundle.esm.js -bundle.es5.js +bundle.*.js rollup.config*.js wdio.conf.js postcss.config.js diff --git a/packages/main/bundle.es5.js b/packages/main/bundle.es5.js index 2d783f0a8303..788dda545ff1 100644 --- a/packages/main/bundle.es5.js +++ b/packages/main/bundle.es5.js @@ -1,33 +1,6 @@ // ES5 bundle targets IE11 only import "@ui5/webcomponents-base/dist/features/browsersupport/IE11.js"; -import "./bundle.esm.js"; +import testAssets from "./bundle.esm.js"; -import { getAnimationMode, setAnimationMode } from "@ui5/webcomponents-base/dist/config/AnimationMode.js"; -import { getTheme, setTheme } from "@ui5/webcomponents-base/dist/config/Theme.js"; -import { getLanguage, setLanguage } from "@ui5/webcomponents-base/dist/config/Language.js"; -import { setNoConflict } from "@ui5/webcomponents-base/dist/config/NoConflict.js"; -import { getRTL } from "@ui5/webcomponents-base/dist/config/RTL.js"; -import { getFirstDayOfWeek } from "@ui5/webcomponents-base/dist/config/FormatSettings.js"; -import { getRegisteredNames as getIconNames } from "@ui5/webcomponents-base/dist/SVGIconRegistry.js"; -import applyDirection from "@ui5/webcomponents-base/dist/locale/applyDirection.js"; -import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js"; -import { addCustomCSS } from "@ui5/webcomponents-base/dist/Theming.js"; - -const configuration = { - getAnimationMode, - setAnimationMode, - getTheme, - setTheme, - getLanguage, - setLanguage, - setNoConflict, - getRTL, - getFirstDayOfWeek, -}; -export { - configuration, - applyDirection, - ResizeHandler, - addCustomCSS, -}; +export default testAssets; diff --git a/packages/main/bundle.esm.js b/packages/main/bundle.esm.js index 01592500f224..6884f2d59b62 100644 --- a/packages/main/bundle.esm.js +++ b/packages/main/bundle.esm.js @@ -87,8 +87,6 @@ window.RenderScheduler = RenderScheduler; import { isIE } from "@ui5/webcomponents-base/dist/Device.js"; window.isIE = isIE; // attached to the window object for testing purposes - -// Note: keep in sync with rollup.config value for IIFE import { getAnimationMode, setAnimationMode } from "@ui5/webcomponents-base/dist/config/AnimationMode.js"; import { getTheme, setTheme } from "@ui5/webcomponents-base/dist/config/Theme.js"; import { getLanguage, setLanguage } from "@ui5/webcomponents-base/dist/config/Language.js"; @@ -99,7 +97,8 @@ import { getRegisteredNames as getIconNames } from "@ui5/webcomponents-base/dis import applyDirection from "@ui5/webcomponents-base/dist/locale/applyDirection.js"; import ResizeHandler from "@ui5/webcomponents-base/dist/delegate/ResizeHandler.js"; import { addCustomCSS } from "@ui5/webcomponents-base/dist/Theming"; -window["sap-ui-webcomponents-bundle"] = { + +const testAssets = { configuration : { getAnimationMode, setAnimationMode, @@ -115,4 +114,9 @@ window["sap-ui-webcomponents-bundle"] = { applyDirection, ResizeHandler, addCustomCSS, + getIconNames, }; + +window["sap-ui-webcomponents-bundle"] = testAssets; + +export default testAssets; diff --git a/packages/main/bundle.scoped.es5.js b/packages/main/bundle.scoped.es5.js new file mode 100644 index 000000000000..8f60488d88a6 --- /dev/null +++ b/packages/main/bundle.scoped.es5.js @@ -0,0 +1,6 @@ +// ES5 bundle targets IE11 only +import "@ui5/webcomponents-base/dist/features/browsersupport/IE11.js"; + +import testAssets from "./bundle.scoped.esm.js"; + +export default testAssets; diff --git a/packages/main/bundle.scoped.esm.js b/packages/main/bundle.scoped.esm.js new file mode 100644 index 000000000000..a66da825b747 --- /dev/null +++ b/packages/main/bundle.scoped.esm.js @@ -0,0 +1,7 @@ +import { setCustomElementsScopingSuffix, setCustomElementsScopingRules } from "@ui5/webcomponents-base/dist/CustomElementsScope.js"; +setCustomElementsScopingSuffix("demo"); +// setCustomElementsScopingRules({include: [/^ui5-/], exclude: [/^ui5-button/, /ui5-icon/]}); + +import testAssets from "./bundle.esm.js"; + +export default testAssets; diff --git a/packages/main/package.json b/packages/main/package.json index 70cfaed7394d..69f29b70b87e 100644 --- a/packages/main/package.json +++ b/packages/main/package.json @@ -2,6 +2,9 @@ "name": "@ui5/webcomponents", "version": "1.0.0-rc.8", "description": "UI5 Web Components: webcomponents.main", + "ui5": { + "webComponentsPackage": true + }, "author": "SAP SE (https://www.sap.com)", "license": "Apache-2.0", "private": false, diff --git a/packages/main/src/Avatar.js b/packages/main/src/Avatar.js index f799bba419f0..4ed5813690c3 100644 --- a/packages/main/src/Avatar.js +++ b/packages/main/src/Avatar.js @@ -211,11 +211,12 @@ class Avatar extends UI5Element { return AvatarTemplate; } + static get dependencies() { + return [Icon]; + } + static async onDefine() { - await Promise.all([ - fetchI18nBundle("@ui5/webcomponents"), - Icon.define(), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } get validInitials() { diff --git a/packages/main/src/BusyIndicator.js b/packages/main/src/BusyIndicator.js index 2e7c42f7dfb6..82e678d82c9b 100644 --- a/packages/main/src/BusyIndicator.js +++ b/packages/main/src/BusyIndicator.js @@ -149,11 +149,12 @@ class BusyIndicator extends UI5Element { return BusyIndicatorTemplate; } + static get dependencies() { + return [Label]; + } + static async onDefine() { - await Promise.all([ - fetchI18nBundle("@ui5/webcomponents"), - Label.define(), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } get ariaTitle() { diff --git a/packages/main/src/Button.js b/packages/main/src/Button.js index eb14f30e71ee..cca223285988 100644 --- a/packages/main/src/Button.js +++ b/packages/main/src/Button.js @@ -283,6 +283,10 @@ class Button extends UI5Element { return ButtonTemplate; } + static get dependencies() { + return [Icon]; + } + constructor() { super(); @@ -406,10 +410,7 @@ class Button extends UI5Element { } static async onDefine() { - await Promise.all([ - Icon.define(), - fetchI18nBundle("@ui5/webcomponents"), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } } diff --git a/packages/main/src/Calendar.js b/packages/main/src/Calendar.js index 004b2d17a101..6b81a18322c8 100644 --- a/packages/main/src/Calendar.js +++ b/packages/main/src/Calendar.js @@ -350,7 +350,7 @@ class Calendar extends UI5Element { let fistDayOfMonthIndex = -1; // focus first day of the month - const dayPicker = this.shadowRoot.querySelector("ui5-daypicker"); + const dayPicker = this.shadowRoot.querySelector("[ui5-daypicker]"); dayPicker._getVisibleDays(targetDate).forEach((date, index) => { if (date.getDate() === 1 && (fistDayOfMonthIndex === -1)) { @@ -431,7 +431,7 @@ class Calendar extends UI5Element { iNewYear = this._calendarDate.getYear(); // focus first day of the month - const dayPicker = this.shadowRoot.querySelector("ui5-daypicker"); + const dayPicker = this.shadowRoot.querySelector("[ui5-daypicker]"); const currentMonthDate = dayPicker._calendarDate.setMonth(dayPicker._calendarDate.getMonth()); const lastMonthDate = dayPicker._calendarDate.setMonth(dayPicker._calendarDate.getMonth() - 1); @@ -693,14 +693,17 @@ class Calendar extends UI5Element { }; } + static get dependencies() { + return [ + CalendarHeader, + DayPicker, + MonthPicker, + YearPicker, + ]; + } + static async onDefine() { - await Promise.all([ - fetchCldr(getLocale().getLanguage(), getLocale().getRegion(), getLocale().getScript()), - CalendarHeader.define(), - DayPicker.define(), - MonthPicker.define(), - YearPicker.define(), - ]); + await fetchCldr(getLocale().getLanguage(), getLocale().getRegion(), getLocale().getScript()); } } diff --git a/packages/main/src/CalendarHeader.js b/packages/main/src/CalendarHeader.js index fca9fc69cf7d..f4fc5e165da5 100644 --- a/packages/main/src/CalendarHeader.js +++ b/packages/main/src/CalendarHeader.js @@ -64,6 +64,10 @@ class CalendarHeader extends UI5Element { return styles; } + static get dependencies() { + return [Button, Icon]; + } + constructor() { super(); this._btnPrev = {}; @@ -119,13 +123,6 @@ class CalendarHeader extends UI5Element { } } } - - static async onDefine() { - await Promise.all([ - await Button.define(), - await Icon.define(), - ]); - } } CalendarHeader.define(); diff --git a/packages/main/src/Card.js b/packages/main/src/Card.js index 0328a777322e..190e96f03790 100644 --- a/packages/main/src/Card.js +++ b/packages/main/src/Card.js @@ -236,11 +236,12 @@ class Card extends UI5Element { return !!this.action.length; } + static get dependencies() { + return [Icon]; + } + static async onDefine() { - await Promise.all([ - Icon.define(), - fetchI18nBundle("@ui5/webcomponents"), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } _headerClick() { diff --git a/packages/main/src/Carousel.js b/packages/main/src/Carousel.js index 606b6a659cfd..8da00c01d90f 100644 --- a/packages/main/src/Carousel.js +++ b/packages/main/src/Carousel.js @@ -26,6 +26,7 @@ import "@ui5/webcomponents-icons/dist/icons/slim-arrow-left.js"; import "@ui5/webcomponents-icons/dist/icons/slim-arrow-right.js"; import Button from "./Button.js"; +import Label from "./Label.js"; // Styles import CarouselCss from "./generated/themes/Carousel.css.js"; @@ -504,11 +505,15 @@ class Carousel extends UI5Element { return this.content.length ? `${this._id}-carousel-item-${this.selectedIndex + 1}` : undefined; } + static get dependencies() { + return [ + Button, + Label, + ]; + } + static async onDefine() { - await Promise.all([ - fetchI18nBundle("@ui5/webcomponents"), - Button.define(), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } } diff --git a/packages/main/src/CheckBox.js b/packages/main/src/CheckBox.js index bbf526703ec8..cfdfb3b7faf0 100644 --- a/packages/main/src/CheckBox.js +++ b/packages/main/src/CheckBox.js @@ -318,12 +318,15 @@ class CheckBox extends UI5Element { return this.disabled ? undefined : tabindex || "0"; } + static get dependencies() { + return [ + Label, + Icon, + ]; + } + static async onDefine() { - await Promise.all([ - Label.define(), - Icon.define(), - fetchI18nBundle("@ui5/webcomponents"), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } } diff --git a/packages/main/src/ComboBox.js b/packages/main/src/ComboBox.js index 72b686d5d858..0bfc163e7a88 100644 --- a/packages/main/src/ComboBox.js +++ b/packages/main/src/ComboBox.js @@ -674,7 +674,7 @@ class ComboBox extends UI5Element { async _respPopover() { const staticAreaItem = await this.getStaticAreaItemDomRef(); - this.responsivePopover = staticAreaItem.querySelector("ui5-responsive-popover"); + this.responsivePopover = staticAreaItem.querySelector("[ui5-responsive-popover]"); return this.responsivePopover; } @@ -736,6 +736,19 @@ class ComboBox extends UI5Element { return getEffectiveAriaLabelText(this); } + static get dependencies() { + return [ + ComboBoxItem, + Icon, + ResponsivePopover, + List, + BusyIndicator, + Button, + StandardListItem, + Popover, + ]; + } + get styles() { return { popoverHeader: { @@ -760,19 +773,6 @@ class ComboBox extends UI5Element { }, }; } - - static async onDefine() { - await Promise.all([ - ComboBoxItem.define(), - Icon.define(), - Popover.define(), - ResponsivePopover.define(), - List.define(), - BusyIndicator.define(), - Button.define(), - StandardListItem.define(), - ]); - } } ComboBox.define(); diff --git a/packages/main/src/DatePicker.js b/packages/main/src/DatePicker.js index 4f07ec838863..2762b9b9daf7 100644 --- a/packages/main/src/DatePicker.js +++ b/packages/main/src/DatePicker.js @@ -16,6 +16,7 @@ import "@ui5/webcomponents-icons/dist/icons/appointment-2.js"; import "@ui5/webcomponents-icons/dist/icons/decline.js"; import { DATEPICKER_OPEN_ICON_TITLE, DATEPICKER_DATE_ACC_TEXT, INPUT_SUGGESTIONS_TITLE } from "./generated/i18n/i18n-defaults.js"; import Icon from "./Icon.js"; +import Button from "./Button.js"; import ResponsivePopover from "./ResponsivePopover.js"; import Calendar from "./Calendar.js"; import Input from "./Input.js"; @@ -472,7 +473,7 @@ class DatePicker extends UI5Element { } _getInput() { - return this.shadowRoot.querySelector("ui5-input"); + return this.shadowRoot.querySelector("[ui5-input]"); } async _handleInputChange() { @@ -685,7 +686,7 @@ class DatePicker extends UI5Element { async _respPopover() { const staticAreaItem = await this.getStaticAreaItemDomRef(); - return staticAreaItem.querySelector("ui5-responsive-popover"); + return staticAreaItem.querySelector("[ui5-responsive-popover]"); } _canOpenPicker() { @@ -846,13 +847,19 @@ class DatePicker extends UI5Element { return InputType.Text; } + static get dependencies() { + return [ + Icon, + ResponsivePopover, + Calendar, + Input, + Button, + ]; + } + static async onDefine() { await Promise.all([ fetchCldr(getLocale().getLanguage(), getLocale().getRegion(), getLocale().getScript()), - Icon.define(), - ResponsivePopover.define(), - Calendar.define(), - Input.define(), fetchI18nBundle("@ui5/webcomponents"), ]); } diff --git a/packages/main/src/DateRangePicker.js b/packages/main/src/DateRangePicker.js index 5aab31b42616..4bde3f69993a 100644 --- a/packages/main/src/DateRangePicker.js +++ b/packages/main/src/DateRangePicker.js @@ -89,10 +89,6 @@ class DateRangePicker extends DatePicker { return DateRangePickerTemplate; } - static async onDefine() { - await DatePicker.define(); - } - constructor() { super(); this.isFirstDatePick = true; diff --git a/packages/main/src/DateTimePicker.js b/packages/main/src/DateTimePicker.js index bec04fdb488b..5520363d91c1 100644 --- a/packages/main/src/DateTimePicker.js +++ b/packages/main/src/DateTimePicker.js @@ -179,15 +179,15 @@ class DateTimePicker extends DatePicker { return [super.staticAreaStyles, DateTimePickerPopoverCss]; } - static async onDefine() { - await Promise.all([ - DatePicker.define(), - Calendar.define(), - Button.define(), - ToggleButton.define(), - SegmentedButton.define(), - WheelSlider.define(), - ]); + static get dependencies() { + return [ + ...DatePicker.dependencies, + Calendar, + Button, + ToggleButton, + SegmentedButton, + WheelSlider, + ]; } constructor() { @@ -557,7 +557,7 @@ class DateTimePicker extends DatePicker { async getPicker() { const staticAreaItem = await this.getStaticAreaItemDomRef(); - return staticAreaItem.querySelector("ui5-responsive-popover"); + return staticAreaItem.querySelector("[ui5-responsive-popover]"); } async getCurrentDateTime() { diff --git a/packages/main/src/DurationPicker.js b/packages/main/src/DurationPicker.js index c1bef447abe3..891e436f2df2 100644 --- a/packages/main/src/DurationPicker.js +++ b/packages/main/src/DurationPicker.js @@ -11,6 +11,8 @@ import PopoverHorizontalAlign from "./types/PopoverHorizontalAlign.js"; import WheelSlider from "./WheelSlider.js"; import ResponsivePopover from "./ResponsivePopover.js"; import Input from "./Input.js"; +import Icon from "./Icon.js"; +import Button from "./Button.js"; import "@ui5/webcomponents-icons/dist/icons/fob-watch.js"; import DurationPickerPopoverTemplate from "./generated/templates/DurationPickerPopoverTemplate.lit.js"; import { @@ -495,7 +497,7 @@ class DurationPicker extends UI5Element { } const staticAreaItem = await this.getStaticAreaItemDomRef(); - this.responsivePopover = staticAreaItem.querySelector("ui5-responsive-popover"); + this.responsivePopover = staticAreaItem.querySelector("[ui5-responsive-popover]"); return this.responsivePopover; } @@ -581,13 +583,18 @@ class DurationPicker extends UI5Element { }; } - static async onDefine(...params) { - await Promise.all([ - fetchI18nBundle("@ui5/webcomponents"), - WheelSlider.define(), - ResponsivePopover.define(), - Input.define(), - ]); + static get dependencies() { + return [ + Icon, + WheelSlider, + ResponsivePopover, + Input, + Button, + ]; + } + + static async onDefine() { + await fetchI18nBundle("@ui5/webcomponents"); } } diff --git a/packages/main/src/FileUploader.js b/packages/main/src/FileUploader.js index c63065d2b23c..5804ebd6b033 100644 --- a/packages/main/src/FileUploader.js +++ b/packages/main/src/FileUploader.js @@ -338,11 +338,12 @@ class FileUploader extends UI5Element { return "file"; } + static get dependencies() { + return [Input]; + } + static async onDefine() { - await Promise.all([ - Input.define(), - fetchI18nBundle("@ui5/webcomponents"), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } } diff --git a/packages/main/src/Input.js b/packages/main/src/Input.js index 6a7d4f00b9d5..327545427801 100644 --- a/packages/main/src/Input.js +++ b/packages/main/src/Input.js @@ -628,7 +628,7 @@ class Input extends UI5Element { this.previousValue = this.value; await this.getInputDOMRef(); - this._inputIconFocused = event.target && event.target === this.querySelector("ui5-icon"); + this._inputIconFocused = event.target && event.target === this.querySelector("[ui5-icon]"); } _onfocusout(event) { @@ -754,7 +754,7 @@ class Input extends UI5Element { async _getPopover() { const staticAreaItem = await this.getStaticAreaItemDomRef(); - return staticAreaItem.querySelector("ui5-popover"); + return staticAreaItem.querySelector("[ui5-popover]"); } enableSuggestions() { @@ -1110,11 +1110,14 @@ class Input extends UI5Element { return isPhone(); } + static get dependencies() { + const Suggestions = getFeature("InputSuggestions"); + + return [Popover].concat(Suggestions ? Suggestions.dependencies : []); + } + static async onDefine() { - await Promise.all([ - Popover.define(), - fetchI18nBundle("@ui5/webcomponents"), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } } diff --git a/packages/main/src/List.js b/packages/main/src/List.js index 3a9d18acdb78..4f1522cea780 100644 --- a/packages/main/src/List.js +++ b/packages/main/src/List.js @@ -771,8 +771,8 @@ class List extends UI5Element { }, delay); } - static async onDefine() { - await BusyIndicator.define(); + static get dependencies() { + return [BusyIndicator]; } } diff --git a/packages/main/src/ListItem.js b/packages/main/src/ListItem.js index 6022520d3b45..d8f8e00bfb3a 100644 --- a/packages/main/src/ListItem.js +++ b/packages/main/src/ListItem.js @@ -5,9 +5,9 @@ import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18 import ListItemType from "./types/ListItemType.js"; import ListMode from "./types/ListMode.js"; import ListItemBase from "./ListItemBase.js"; -import "./RadioButton.js"; -import "./CheckBox.js"; -import "./Button.js"; +import RadioButton from "./RadioButton.js"; +import CheckBox from "./CheckBox.js"; +import Button from "./Button.js"; import { DELETE, ARIA_LABEL_LIST_ITEM_CHECKBOX } from "./generated/i18n/i18n-defaults.js"; // Styles @@ -96,6 +96,14 @@ class ListItem extends ListItemBase { return [ListItemBase.styles, styles]; } + static get dependencies() { + return [ + Button, + RadioButton, + CheckBox, + ]; + } + constructor() { super(); diff --git a/packages/main/src/MessageStrip.js b/packages/main/src/MessageStrip.js index 4d806d86d421..81a0ef137d85 100644 --- a/packages/main/src/MessageStrip.js +++ b/packages/main/src/MessageStrip.js @@ -160,12 +160,15 @@ class MessageStrip extends UI5Element { this.fireEvent("close", {}); } + static get dependencies() { + return [ + Icon, + Button, + ]; + } + static async onDefine() { - await Promise.all([ - fetchI18nBundle("@ui5/webcomponents"), - Icon.define(), - Button.define(), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } static typeClassesMappings() { diff --git a/packages/main/src/MultiComboBox.js b/packages/main/src/MultiComboBox.js index 2d7b5b3a51b2..6cb6f9cf8d97 100644 --- a/packages/main/src/MultiComboBox.js +++ b/packages/main/src/MultiComboBox.js @@ -17,6 +17,7 @@ import ResponsivePopover from "./ResponsivePopover.js"; import List from "./List.js"; import StandardListItem from "./StandardListItem.js"; import ToggleButton from "./ToggleButton.js"; +import Button from "./Button.js"; import { VALUE_STATE_SUCCESS, VALUE_STATE_ERROR, @@ -303,6 +304,20 @@ class MultiComboBox extends UI5Element { return ResponsivePopoverCommonCss; } + static get dependencies() { + return [ + MultiComboBoxItem, + Tokenizer, + Token, + Icon, + ResponsivePopover, + List, + StandardListItem, + ToggleButton, + Button, + ]; + } + constructor() { super(); @@ -417,7 +432,7 @@ class MultiComboBox extends UI5Element { } _tokenizerFocusOut() { - const tokenizer = this.shadowRoot.querySelector("ui5-tokenizer"); + const tokenizer = this.shadowRoot.querySelector("[ui5-tokenizer]"); const tokensCount = tokenizer.tokens.length - 1; tokenizer.tokens.forEach(token => { token.selected = false; }); @@ -571,7 +586,7 @@ class MultiComboBox extends UI5Element { } get _tokenizer() { - return this.shadowRoot.querySelector("ui5-tokenizer"); + return this.shadowRoot.querySelector("[ui5-tokenizer]"); } get nMoreCountText() { @@ -643,17 +658,7 @@ class MultiComboBox extends UI5Element { } static async onDefine() { - await Promise.all([ - MultiComboBoxItem.define(), - Tokenizer.define(), - Token.define(), - Icon.define(), - ResponsivePopover.define(), - List.define(), - StandardListItem.define(), - ToggleButton, - fetchI18nBundle("@ui5/webcomponents"), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } } diff --git a/packages/main/src/MultiInput.js b/packages/main/src/MultiInput.js index 3824f586c285..883b962294c6 100644 --- a/packages/main/src/MultiInput.js +++ b/packages/main/src/MultiInput.js @@ -185,15 +185,16 @@ class MultiInput extends Input { } get tokenizer() { - return this.shadowRoot.querySelector("ui5-tokenizer"); + return this.shadowRoot.querySelector("[ui5-tokenizer]"); } - static async onDefine() { - await Promise.all([ - Tokenizer.define(), - Token.define(), - Icon.define(), - ]); + static get dependencies() { + return [ + ...Input.dependencies, + Tokenizer, + Token, + Icon, + ]; } } diff --git a/packages/main/src/Panel.js b/packages/main/src/Panel.js index 7c317ba96e5d..21fb157babc9 100644 --- a/packages/main/src/Panel.js +++ b/packages/main/src/Panel.js @@ -424,11 +424,12 @@ class Panel extends UI5Element { }; } + static get dependencies() { + return [Button]; + } + static async onDefine() { - await Promise.all([ - fetchI18nBundle("@ui5/webcomponents"), - Button.define(), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } } diff --git a/packages/main/src/RadioButton.js b/packages/main/src/RadioButton.js index 751436d96d41..63b58a96621a 100644 --- a/packages/main/src/RadioButton.js +++ b/packages/main/src/RadioButton.js @@ -230,11 +230,12 @@ class RadioButton extends UI5Element { return radioButtonCss; } + static get dependencies() { + return [Label]; + } + static async onDefine() { - await Promise.all([ - Label.define(), - fetchI18nBundle("@ui5/webcomponents"), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } onBeforeRendering() { diff --git a/packages/main/src/ResponsivePopover.js b/packages/main/src/ResponsivePopover.js index e68e47ac22a2..d7cf448d341e 100644 --- a/packages/main/src/ResponsivePopover.js +++ b/packages/main/src/ResponsivePopover.js @@ -87,12 +87,12 @@ class ResponsivePopover extends Popover { return ResponsivePopoverTemplate; } - static async onDefine() { - await Promise.all([ - Button.define(), - Dialog.define(), - Title.define(), - ]); + static get dependencies() { + return [ + Button, + Dialog, + Title, + ]; } /** @@ -155,7 +155,7 @@ class ResponsivePopover extends Popover { } get _dialog() { - return this.shadowRoot.querySelector("ui5-dialog"); + return this.shadowRoot.querySelector("[ui5-dialog]"); } get _isPhone() { diff --git a/packages/main/src/SegmentedButton.js b/packages/main/src/SegmentedButton.js index b35dff6f385a..b7d22788d375 100644 --- a/packages/main/src/SegmentedButton.js +++ b/packages/main/src/SegmentedButton.js @@ -96,11 +96,12 @@ class SegmentedButton extends UI5Element { return SegmentedButtonCss; } + static get dependencies() { + return [ToggleButton]; + } + static async onDefine() { - await Promise.all([ - fetchI18nBundle("@ui5/webcomponents"), - ToggleButton.define(), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } constructor() { diff --git a/packages/main/src/Select.js b/packages/main/src/Select.js index 5dc2f56c0fac..dddd39d9f82e 100644 --- a/packages/main/src/Select.js +++ b/packages/main/src/Select.js @@ -31,6 +31,7 @@ import Popover from "./Popover.js"; import List from "./List.js"; import StandardListItem from "./StandardListItem.js"; import Icon from "./Icon.js"; +import Button from "./Button.js"; // Templates import SelectTemplate from "./generated/templates/SelectTemplate.lit.js"; @@ -281,7 +282,7 @@ class Select extends UI5Element { async _respPopover() { this._iconPressed = true; const staticAreaItem = await this.getStaticAreaItemDomRef(); - return staticAreaItem.querySelector("ui5-responsive-popover"); + return staticAreaItem.querySelector("[ui5-responsive-popover]"); } /** @@ -605,19 +606,20 @@ class Select extends UI5Element { async _getPopover() { const staticAreaItem = await this.getStaticAreaItemDomRef(); - return staticAreaItem.querySelector("ui5-popover"); - } - - static async onDefine() { - await Promise.all([ - Option.define(), - Label.define(), - ResponsivePopover.define(), - Popover.define(), - List.define(), - StandardListItem.define(), - Icon.define(), - ]); + return staticAreaItem.querySelector("[ui5-popover]"); + } + + static get dependencies() { + return [ + Option, + Label, + ResponsivePopover, + Popover, + List, + StandardListItem, + Icon, + Button, + ]; } } diff --git a/packages/main/src/StandardListItem.js b/packages/main/src/StandardListItem.js index 8cd214ebc783..56841de84720 100644 --- a/packages/main/src/StandardListItem.js +++ b/packages/main/src/StandardListItem.js @@ -151,11 +151,12 @@ class StandardListItem extends ListItem { return (this.icon && this.iconEnd); } - static async onDefine() { - await Promise.all([ - Icon.define(), - Avatar.define(), - ]); + static get dependencies() { + return [ + ...ListItem.dependencies, + Icon, + Avatar, + ]; } } diff --git a/packages/main/src/SuggestionItem.js b/packages/main/src/SuggestionItem.js index c5b5dcd0fc6a..9f084b2272d1 100644 --- a/packages/main/src/SuggestionItem.js +++ b/packages/main/src/SuggestionItem.js @@ -146,11 +146,11 @@ class SuggestionItem extends UI5Element { return metadata; } - static async onDefine() { - await Promise.all([ - SuggestionListItem.define(), - GroupHeaderListItem.define(), - ]); + static get dependencies() { + return [ + SuggestionListItem, + GroupHeaderListItem, + ]; } } diff --git a/packages/main/src/Switch.js b/packages/main/src/Switch.js index 1bd93c9655c9..75cd7c264058 100644 --- a/packages/main/src/Switch.js +++ b/packages/main/src/Switch.js @@ -227,11 +227,12 @@ class Switch extends UI5Element { return this.checked ? this.accessibilityOnText : this.accessibilityOffText; } + static get dependencies() { + return [Icon]; + } + static async onDefine() { - await Promise.all([ - Icon.define(), - fetchI18nBundle("@ui5/webcomponents"), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } } diff --git a/packages/main/src/Tab.js b/packages/main/src/Tab.js index d0850b607c56..6f45d85749d4 100644 --- a/packages/main/src/Tab.js +++ b/packages/main/src/Tab.js @@ -1,5 +1,6 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; +import executeTemplate from "@ui5/webcomponents-base/dist/renderer/executeTemplate.js"; import SemanticColor from "./types/SemanticColor.js"; import TabLayout from "./types/TabLayout.js"; import TabContainer from "./TabContainer.js"; @@ -170,11 +171,11 @@ class Tab extends UI5Element { return css; } - static async onDefine() { - await Promise.all([ - Icon.define(), - CustomListItem.define(), - ]); + static get dependencies() { + return [ + Icon, + CustomListItem, + ]; } get isSeparator() { @@ -182,11 +183,11 @@ class Tab extends UI5Element { } get stripPresentation() { - return this.constructor.stripTemplate(this); + return executeTemplate(this.constructor.stripTemplate, this); } get overflowPresentation() { - return this.constructor.overflowTemplate(this); + return executeTemplate(this.constructor.overflowTemplate, this); } getFocusDomRef() { diff --git a/packages/main/src/TabContainer.js b/packages/main/src/TabContainer.js index 6d500ae3003e..8ba34368cb83 100644 --- a/packages/main/src/TabContainer.js +++ b/packages/main/src/TabContainer.js @@ -552,14 +552,17 @@ class TabContainer extends UI5Element { return getAnimationMode() !== AnimationMode.None; } + static get dependencies() { + return [ + Button, + Icon, + List, + ResponsivePopover, + ]; + } + static async onDefine() { - await Promise.all([ - Button.define(), - Icon.define(), - List.define(), - ResponsivePopover.define(), - fetchI18nBundle("@ui5/webcomponents"), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } } diff --git a/packages/main/src/TextArea.js b/packages/main/src/TextArea.js index a729b7a0dc25..75346873c3c8 100644 --- a/packages/main/src/TextArea.js +++ b/packages/main/src/TextArea.js @@ -454,7 +454,7 @@ class TextArea extends UI5Element { async _getPopover() { const staticAreaItem = await this.getStaticAreaItemDomRef(); - return staticAreaItem.querySelector("ui5-popover"); + return staticAreaItem.querySelector("[ui5-popover]"); } _tokenizeText(value) { @@ -585,11 +585,12 @@ class TextArea extends UI5Element { }; } + static get dependencies() { + return [Popover]; + } + static async onDefine() { - await Promise.all([ - Popover.define(), - fetchI18nBundle("@ui5/webcomponents"), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } } diff --git a/packages/main/src/TimePicker.js b/packages/main/src/TimePicker.js index b46c6ba7076f..3a28aeee1b02 100644 --- a/packages/main/src/TimePicker.js +++ b/packages/main/src/TimePicker.js @@ -22,12 +22,14 @@ import { isPageDownShiftCtrl, } from "@ui5/webcomponents-base/src/Keys.js"; import "@ui5/webcomponents-icons/dist/icons/time-entry-request.js"; +import Icon from "./Icon.js"; import PopoverHorizontalAlign from "./types/PopoverHorizontalAlign.js"; import ResponsivePopover from "./ResponsivePopover.js"; import PopoverPlacementType from "./types/PopoverPlacementType.js"; import TimePickerTemplate from "./generated/templates/TimePickerTemplate.lit.js"; import TimePickerPopoverTemplate from "./generated/templates/TimePickerPopoverTemplate.lit.js"; import Input from "./Input.js"; +import Button from "./Button.js"; import WheelSlider from "./WheelSlider.js"; import { getHours, @@ -286,13 +288,20 @@ class TimePicker extends UI5Element { return TimePickerTemplate; } + static get dependencies() { + return [ + Icon, + ResponsivePopover, + WheelSlider, + Input, + Button, + ]; + } + static async onDefine() { await Promise.all([ fetchCldr(getLocale().getLanguage(), getLocale().getRegion(), getLocale().getScript()), - ResponsivePopover.define(), fetchI18nBundle("@ui5/webcomponents"), - WheelSlider.define(), - Input.define(), ]); } @@ -476,7 +485,7 @@ class TimePicker extends UI5Element { async _getPopover() { const staticAreaItem = await this.getStaticAreaItemDomRef(); - this.responsivePopover = staticAreaItem.querySelector("ui5-responsive-popover"); + this.responsivePopover = staticAreaItem.querySelector("[ui5-responsive-popover]"); return this.responsivePopover; } @@ -502,7 +511,7 @@ class TimePicker extends UI5Element { } _getInput() { - return this.shadowRoot.querySelector("ui5-input"); + return this.shadowRoot.querySelector("[ui5-input]"); } _getInputField() { diff --git a/packages/main/src/Timeline.js b/packages/main/src/Timeline.js index 2a2bec6e27ec..946b6f61710c 100644 --- a/packages/main/src/Timeline.js +++ b/packages/main/src/Timeline.js @@ -76,11 +76,12 @@ class Timeline extends UI5Element { this.i18nBundle = getI18nBundle("@ui5/webcomponents"); } + static get dependencies() { + return [TimelineItem]; + } + static async onDefine() { - await Promise.all([ - TimelineItem.define(), - fetchI18nBundle("@ui5/webcomponents"), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } initItemNavigation() { diff --git a/packages/main/src/TimelineItem.js b/packages/main/src/TimelineItem.js index 4c6c7ab4a48d..b374a8b85903 100644 --- a/packages/main/src/TimelineItem.js +++ b/packages/main/src/TimelineItem.js @@ -143,11 +143,11 @@ class TimelineItem extends UI5Element { this.fireEvent("item-name-click", {}); } - static async onDefine() { - await Promise.all([ - Icon.define(), - Link.define(), - ]); + static get dependencies() { + return [ + Icon, + Link, + ]; } } diff --git a/packages/main/src/Token.js b/packages/main/src/Token.js index 38f4d165baf1..d69759321a02 100644 --- a/packages/main/src/Token.js +++ b/packages/main/src/Token.js @@ -150,11 +150,12 @@ class Token extends UI5Element { return getTheme() === "sap_fiori_3" ? "decline" : "sys-cancel"; } + static get dependencies() { + return [Icon]; + } + static async onDefine() { - await Promise.all([ - Icon.define(), - fetchI18nBundle("@ui5/webcomponents"), - ]); + await fetchI18nBundle("@ui5/webcomponents"); } } diff --git a/packages/main/src/Tokenizer.js b/packages/main/src/Tokenizer.js index 326fa6d0884c..f95222a77a2d 100644 --- a/packages/main/src/Tokenizer.js +++ b/packages/main/src/Tokenizer.js @@ -5,6 +5,9 @@ import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation import ScrollEnablement from "@ui5/webcomponents-base/dist/delegate/ScrollEnablement.js"; import Integer from "@ui5/webcomponents-base/dist/types/Integer.js"; import { fetchI18nBundle, getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; +import ResponsivePopover from "./ResponsivePopover.js"; +import List from "./List.js"; +import StandardListItem from "./StandardListItem.js"; import TokenizerTemplate from "./generated/templates/TokenizerTemplate.lit.js"; import TokenizerPopoverTemplate from "./generated/templates/TokenizerPopoverTemplate.lit.js"; import { MULTIINPUT_SHOW_MORE_TOKENS, TOKENIZER_ARIA_LABEL, TOKENIZER_POPOVER_REMOVE } from "./generated/i18n/i18n-defaults.js"; @@ -274,12 +277,20 @@ class Tokenizer extends UI5Element { }; } + static get dependencies() { + return [ + ResponsivePopover, + List, + StandardListItem, + ]; + } + static async onDefine() { await fetchI18nBundle("@ui5/webcomponents"); } async getPopover() { - return (await this.getStaticAreaItemDomRef()).querySelector("ui5-responsive-popover"); + return (await this.getStaticAreaItemDomRef()).querySelector("[ui5-responsive-popover]"); } } diff --git a/packages/main/src/Tree.js b/packages/main/src/Tree.js index f2c9f5939f68..477853fdd879 100644 --- a/packages/main/src/Tree.js +++ b/packages/main/src/Tree.js @@ -238,12 +238,12 @@ class Tree extends UI5Element { return TreeTemplate; } - static async onDefine() { - await Promise.all([ - List.define(), - TreeListItem.define(), - TreeItem.define(), - ]); + static get dependencies() { + return [ + List, + TreeListItem, + TreeItem, + ]; } constructor() { diff --git a/packages/main/src/TreeListItem.js b/packages/main/src/TreeListItem.js index 7744ec3df284..fcf852a84906 100644 --- a/packages/main/src/TreeListItem.js +++ b/packages/main/src/TreeListItem.js @@ -168,8 +168,11 @@ class TreeListItem extends ListItem { return metadata; } - static async onDefine() { - await Icon.define(); + static get dependencies() { + return [ + ...ListItem.dependencies, + Icon, + ]; } onBeforeRendering() { diff --git a/packages/main/src/WheelSlider.js b/packages/main/src/WheelSlider.js index cf446a0b19cd..78b207c85279 100644 --- a/packages/main/src/WheelSlider.js +++ b/packages/main/src/WheelSlider.js @@ -174,8 +174,8 @@ class WheelSlider extends UI5Element { this._updateItemCellHeight(); } - static async onDefine() { - await Button.define(); + static get dependencies() { + return [Button]; } onAfterRendering() { diff --git a/packages/main/src/features/InputSuggestions.js b/packages/main/src/features/InputSuggestions.js index 705073858e5c..2c6cef2821be 100644 --- a/packages/main/src/features/InputSuggestions.js +++ b/packages/main/src/features/InputSuggestions.js @@ -3,7 +3,10 @@ import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; import List from "../List.js"; import ResponsivePopover from "../ResponsivePopover.js"; -import "../SuggestionItem.js"; +import SuggestionItem from "../SuggestionItem.js"; +import Button from "../Button.js"; +import GroupHeaderListItem from "../GroupHeaderListItem.js"; +import SuggestionListItem from "../SuggestionListItem.js"; import { LIST_ITEM_POSITION, @@ -322,7 +325,7 @@ class Suggestions { } _getItems() { - return [...this.responsivePopover.querySelector("ui5-list").children]; + return [...this.responsivePopover.querySelector("[ui5-list]").children]; } _getComponent() { @@ -331,7 +334,7 @@ class Suggestions { async _getList() { this.responsivePopover = await this._respPopover(); - return this.responsivePopover.querySelector("ui5-list"); + return this.responsivePopover.querySelector("[ui5-list]"); } async _getListWidth() { @@ -349,7 +352,7 @@ class Suggestions { } const staticAreaItem = await this._getComponent().getStaticAreaItemDomRef(); - this.responsivePopover = staticAreaItem.querySelector("ui5-responsive-popover"); + this.responsivePopover = staticAreaItem.querySelector("[ui5-responsive-popover]"); return this.responsivePopover; } @@ -398,15 +401,21 @@ class Suggestions { sanitizeText(text) { return text && text.replace("<", "<"); } + + static get dependencies() { + return [ + SuggestionItem, + ResponsivePopover, + List, + SuggestionListItem, + GroupHeaderListItem, + Button, + ]; + } } Suggestions.SCROLL_STEP = 60; -// The List and Popover components would be rendered -// by the issuer component`s template. -List.define(); -ResponsivePopover.define(); - // Add suggestions support to the global features registry so that Input.js can use it registerFeature("InputSuggestions", Suggestions); diff --git a/packages/main/src/themes/Badge.css b/packages/main/src/themes/Badge.css index b47f8c412937..5320876db26d 100644 --- a/packages/main/src/themes/Badge.css +++ b/packages/main/src/themes/Badge.css @@ -20,13 +20,13 @@ padding: 0 0.3125em; } -::slotted(ui5-icon) { +::slotted([ui5-icon]) { width: .75em; height: .75em; } /* IE 11 specific selector */ -ui5-badge ui5-icon[slot="icon"] { +[ui5-badge] [ui5-icon][slot="icon"] { display: flex; } diff --git a/packages/main/src/themes/Button.css b/packages/main/src/themes/Button.css index 3886f6d1b784..9e3c2788dd7f 100644 --- a/packages/main/src/themes/Button.css +++ b/packages/main/src/themes/Button.css @@ -239,15 +239,15 @@ bdi { /* IE Specific CSS */ -ui5-button[focused] { +[ui5-button][focused] { outline: none; } -ui5-button[focused] .ui5-button-root { +[ui5-button][focused] .ui5-button-root { position: relative; } -ui5-button[focused] .ui5-button-root::after { +[ui5-button][focused] .ui5-button-root::after { content: ""; position: absolute; border-width: 1px; @@ -259,31 +259,31 @@ ui5-button[focused] .ui5-button-root::after { right: var(--_ui5_button_focus_offset); } -ui5-button[active] .ui5-button-root::after { +[ui5-button][active] .ui5-button-root::after { border-color: var(--sapContent_ContrastFocusColor); } -ui5-button[design="Positive"][focused] .ui5-button-root::after { +[ui5-button][design="Positive"][focused] .ui5-button-root::after { border-color: var(--_ui5_button_positive_border_focus_hover_color); } -ui5-button[design="Positive"][active][focused] .ui5-button-root::after { +[ui5-button][design="Positive"][active][focused] .ui5-button-root::after { border-color: var(--sapContent_ContrastFocusColor); } -ui5-button[design="Negative"][focused] .ui5-button-root::after { +[ui5-button][design="Negative"][focused] .ui5-button-root::after { border-color: var(--_ui5_button_positive_border_focus_hover_color); } -ui5-button[design="Negative"][active][focused] .ui5-button-root::after { +[ui5-button][design="Negative"][active][focused] .ui5-button-root::after { border-color: var(--sapContent_ContrastFocusColor); } -ui5-button[design="Emphasized"][focused] .ui5-button-root::after { +[ui5-button][design="Emphasized"][focused] .ui5-button-root::after { border-color: var(--sapContent_ContrastFocusColor); } -ui5-button ui5-icon.ui5-button-icon { +[ui5-button] [ui5-icon].ui5-button-icon { height: var(--_ui5_button_icon_font_size); /* Center vertically all icons*/ top: 0; } diff --git a/packages/main/src/themes/Calendar.css b/packages/main/src/themes/Calendar.css index 5916831c90e5..58aec27cbbac 100644 --- a/packages/main/src/themes/Calendar.css +++ b/packages/main/src/themes/Calendar.css @@ -12,8 +12,8 @@ background: var(--sapList_Background); } -.ui5-cal-root ui5-daypicker, -.ui5-cal-root ui5-month-picker, -.ui5-cal-root ui5-yearpicker { +.ui5-cal-root [ui5-daypicker], +.ui5-cal-root [ui5-month-picker], +.ui5-cal-root [ui5-yearpicker] { vertical-align: top; } diff --git a/packages/main/src/themes/CalendarHeader.css b/packages/main/src/themes/CalendarHeader.css index f285ef0740f9..3324277e9201 100644 --- a/packages/main/src/themes/CalendarHeader.css +++ b/packages/main/src/themes/CalendarHeader.css @@ -10,7 +10,7 @@ box-sizing: border-box; } -.ui5-calheader-root ui5-button { +.ui5-calheader-root [ui5-button] { height: 100%; } diff --git a/packages/main/src/themes/Card.css b/packages/main/src/themes/Card.css index 0a64238c95b1..3841445c0020 100644 --- a/packages/main/src/themes/Card.css +++ b/packages/main/src/themes/Card.css @@ -79,7 +79,7 @@ pointer-events: none; } -::slotted(ui5-icon) { +::slotted([ui5-icon]) { width: 1.5rem; height: 1.5rem; color: var(--sapTile_IconColor); diff --git a/packages/main/src/themes/Carousel.css b/packages/main/src/themes/Carousel.css index 9d8719f75dae..5e0d9d90405b 100644 --- a/packages/main/src/themes/Carousel.css +++ b/packages/main/src/themes/Carousel.css @@ -84,7 +84,7 @@ pointer-events: none; } -.ui5-carousel-navigation-arrows > ui5-button { +.ui5-carousel-navigation-arrows > [ui5-button] { pointer-events: all; } diff --git a/packages/main/src/themes/CustomListItem.css b/packages/main/src/themes/CustomListItem.css index 96bcd52be95f..f55473edecbb 100644 --- a/packages/main/src/themes/CustomListItem.css +++ b/packages/main/src/themes/CustomListItem.css @@ -17,14 +17,14 @@ pointer-events: auto; } -ui5-checkbox.ui5-li-singlesel-radiobtn, -ui5-radiobutton.ui5-li-singlesel-radiobtn { +[ui5-checkbox].ui5-li-singlesel-radiobtn, +[ui5-radiobutton].ui5-li-singlesel-radiobtn { display: flex; align-items: center; } .ui5-li-root.ui5-custom-li-root, -ui5-checkbox.ui5-li-singlesel-radiobtn, -ui5-radiobutton.ui5-li-singlesel-radiobtn { +[ui5-checkbox].ui5-li-singlesel-radiobtn, +[ui5-radiobutton].ui5-li-singlesel-radiobtn { min-width: var(--_ui5_custom_list_item_rb_min_width); -} \ No newline at end of file +} diff --git a/packages/main/src/themes/DatePickerPopover.css b/packages/main/src/themes/DatePickerPopover.css index 9b2fe8f3cfb9..fe93f896c68a 100644 --- a/packages/main/src/themes/DatePickerPopover.css +++ b/packages/main/src/themes/DatePickerPopover.css @@ -1,3 +1,3 @@ -ui5-calendar { +[ui5-calendar] { width: 100%; -} \ No newline at end of file +} diff --git a/packages/main/src/themes/DurationPickerPopover.css b/packages/main/src/themes/DurationPickerPopover.css index 66698dadc9cd..df59b4eb749b 100644 --- a/packages/main/src/themes/DurationPickerPopover.css +++ b/packages/main/src/themes/DurationPickerPopover.css @@ -23,7 +23,7 @@ width: 100%; } -.ui5-duration-picker-footer > ui5-button { +.ui5-duration-picker-footer > [ui5-button] { margin: 1%; min-width: 20%; } diff --git a/packages/main/src/themes/FileUploader.css b/packages/main/src/themes/FileUploader.css index 7702e26a7e57..3f797a94b67b 100644 --- a/packages/main/src/themes/FileUploader.css +++ b/packages/main/src/themes/FileUploader.css @@ -23,16 +23,16 @@ display: flex; } -.ui5-file-uploader-mask ui5-input { +.ui5-file-uploader-mask [ui5-input] { margin-right: 0.25rem; } -:host(:not([value-state]):not([disabled]):hover) ui5-input { +:host(:not([value-state]):not([disabled]):hover) [ui5-input] { background-color: var(--sapField_Hover_Background); border: 1px solid var(--sapField_Hover_BorderColor); } -:host(:not([disabled]):active) ui5-button { +:host(:not([disabled]):active) [ui5-button] { background-color: var(--sapButton_Active_Background); border-color: var(--_ui5_button_active_border_color); color: var(--sapButton_Active_TextColor); diff --git a/packages/main/src/themes/Input.css b/packages/main/src/themes/Input.css index 43fb504c4aa1..15eacd2315e8 100644 --- a/packages/main/src/themes/Input.css +++ b/packages/main/src/themes/Input.css @@ -190,9 +190,9 @@ } /* TODO: Remove this after parser is fixed - - this statement is transformed to "ui5-multi-combobox ui5-icon" which + - this statement is transformed to [ui5-multi-combobox] [ui5-icon] which affects all icons in the combobox incuding these in the list items */ -::slotted(ui5-icon[slot="icon"]) { +::slotted([ui5-icon][slot="icon"]) { padding: var(--_ui5_input_icon_padding); -} \ No newline at end of file +} diff --git a/packages/main/src/themes/ListItem.css b/packages/main/src/themes/ListItem.css index e0b97b2cf07c..d3c265aed54f 100644 --- a/packages/main/src/themes/ListItem.css +++ b/packages/main/src/themes/ListItem.css @@ -32,14 +32,14 @@ color: var(--sapList_Active_TextColor); } -/* ui5-li: title, description, info state */ +/* [ui5-li]: title, description, info state */ :host([active][actionable]) .ui5-li-title, :host([active][actionable]) .ui5-li-desc, :host([active][actionable]) .ui5-li-info { color: var(--sapList_Active_TextColor); } -/* ui5-li: infoState */ +/* [ui5-li]: infoState */ :host([info-state="Warning"]) .ui5-li-info { color: var(--sapCriticalTextColor); } @@ -56,7 +56,7 @@ color: var(--sapInformativeTextColor); } -/* ui5-li: item with title and description */ +/* [ui5-li]: item with title and description */ :host([has-title][description]) { height: 5rem; } @@ -136,7 +136,7 @@ flex-shrink: 0; } -:host ui5-checkbox.ui5-li-singlesel-radiobtn { +:host [ui5-checkbox].ui5-li-singlesel-radiobtn { margin-right: var(--_ui5_list_item_cb_margin_right); } diff --git a/packages/main/src/themes/MultiComboBox.css b/packages/main/src/themes/MultiComboBox.css index c22a65a244e6..75d27f757d08 100644 --- a/packages/main/src/themes/MultiComboBox.css +++ b/packages/main/src/themes/MultiComboBox.css @@ -23,6 +23,6 @@ } /* Workaround for IE */ -ui5-multi-combobox ui5-tokenizer { +[ui5-multi-combobox] [ui5-tokenizer] { flex: 3; } diff --git a/packages/main/src/themes/MultiInput.css b/packages/main/src/themes/MultiInput.css index e218c1ceda83..df6a06eca34c 100644 --- a/packages/main/src/themes/MultiInput.css +++ b/packages/main/src/themes/MultiInput.css @@ -9,6 +9,6 @@ } /* Workaround for IE */ -ui5-multi-input ui5-tokenizer { +[ui5-multi-input] [ui5-tokenizer] { flex: 3; -} \ No newline at end of file +} diff --git a/packages/main/src/themes/RadioButton.css b/packages/main/src/themes/RadioButton.css index cf2666066513..1943154bdc09 100644 --- a/packages/main/src/themes/RadioButton.css +++ b/packages/main/src/themes/RadioButton.css @@ -132,7 +132,7 @@ } /* Label */ -ui5-label.ui5-radio-label { +[ui5-label].ui5-radio-label { display: flex; align-items: center; width: var(--_ui5_rb_label_width); @@ -149,7 +149,7 @@ ui5-label.ui5-radio-label { height: auto; } -:host([wrap][text]) ui5-label.ui5-radio-label { +:host([wrap][text]) [ui5-label].ui5-radio-label { padding: var(--_ui5_rb_label_side_padding) 0; word-break: break-all; } @@ -186,4 +186,4 @@ ui5-label.ui5-radio-label { /* ListItem Context */ :host(.ui5-li-singlesel-radiobtn) .ui5-radio-root .ui5-radio-inner .ui5-radio-svg-outer { fill: var(--sapList_Background); -} \ No newline at end of file +} diff --git a/packages/main/src/themes/SegmentedButton.css b/packages/main/src/themes/SegmentedButton.css index eedc72d4c645..7aab0301c745 100644 --- a/packages/main/src/themes/SegmentedButton.css +++ b/packages/main/src/themes/SegmentedButton.css @@ -6,7 +6,7 @@ display: flex; } -::slotted(ui5-togglebutton) { +::slotted([ui5-togglebutton]) { border-radius: 0; height: var(--_ui5_button_base_height); min-width: 2.5rem; @@ -15,25 +15,25 @@ text-overflow: ellipsis; } -::slotted(ui5-togglebutton:nth-child(odd)) { +::slotted([ui5-togglebutton]:nth-child(odd)) { border: 1px solid var(--sapButton_Selected_BorderColor); border-right: 0; border-left: 0; } -::slotted(ui5-togglebutton:last-child) { +::slotted([ui5-togglebutton]:last-child) { border-top-right-radius: var(--_ui5_segmented_btn_border_radius); border-bottom-right-radius: var(--_ui5_segmented_btn_border_radius); border-right: 1px solid var(--sapButton_Selected_BorderColor); } -::slotted(ui5-togglebutton:first-child) { +::slotted([ui5-togglebutton]:first-child) { border-top-left-radius: var(--_ui5_segmented_btn_border_radius); border-bottom-left-radius: var(--_ui5_segmented_btn_border_radius); border-left: 1px solid var(--sapButton_Selected_BorderColor); } -[dir="rtl"] ::slotted(ui5-togglebutton:first-child) { +[dir="rtl"] ::slotted([ui5-togglebutton]:first-child) { border-top-right-radius: var(--_ui5_segmented_btn_border_radius); border-bottom-right-radius: var(--_ui5_segmented_btn_border_radius); border-top-left-radius: 0; @@ -41,7 +41,7 @@ border-right: 1px solid var(--sapButton_Selected_BorderColor); } -[dir="rtl"] ::slotted(ui5-togglebutton:last-child) { +[dir="rtl"] ::slotted([ui5-togglebutton]:last-child) { border-top-right-radius: 0; border-bottom-right-radius: 0; border-top-left-radius: var(--_ui5_segmented_btn_border_radius); @@ -49,9 +49,9 @@ border-left: 1px solid var(--sapButton_Selected_BorderColor); } -[dir="rtl"] ::slotted(ui5-togglebutton:only-child) { +[dir="rtl"] ::slotted([ui5-togglebutton]:only-child) { border-top-right-radius: var(--_ui5_segmented_btn_border_radius); border-bottom-right-radius: var(--_ui5_segmented_btn_border_radius); border-top-left-radius: var(--_ui5_segmented_btn_border_radius); border-bottom-left-radius: var(--_ui5_segmented_btn_border_radius); -} \ No newline at end of file +} diff --git a/packages/main/src/themes/Select.css b/packages/main/src/themes/Select.css index 30510afd3a6b..26ae0083e170 100644 --- a/packages/main/src/themes/Select.css +++ b/packages/main/src/themes/Select.css @@ -21,7 +21,7 @@ padding-left: 0.5rem; } -.ui5-select-label-root ui5-label { +.ui5-select-label-root [ui5-label] { cursor: pointer; } @@ -32,4 +32,4 @@ :host(:not([disabled])) { cursor: pointer; -} \ No newline at end of file +} diff --git a/packages/main/src/themes/TabInOverflow.css b/packages/main/src/themes/TabInOverflow.css index 7abc374f3b42..edff146a93dc 100644 --- a/packages/main/src/themes/TabInOverflow.css +++ b/packages/main/src/themes/TabInOverflow.css @@ -39,7 +39,7 @@ pointer-events: none; } -.ui5-tab-overflow-item ui5-icon { +.ui5-tab-overflow-item [ui5-icon] { width: 1.375rem; height: 1.375rem; padding-right: 1rem; diff --git a/packages/main/src/themes/TimePickerPopover.css b/packages/main/src/themes/TimePickerPopover.css index aebc7d99874d..9ec332a9f7db 100644 --- a/packages/main/src/themes/TimePickerPopover.css +++ b/packages/main/src/themes/TimePickerPopover.css @@ -24,7 +24,7 @@ padding-right: 0.25rem; } -.ui5-time-picker-footer > ui5-button { +.ui5-time-picker-footer > [ui5-button] { margin: 1%; min-width: 20%; } diff --git a/packages/main/src/themes/ToggleButton.css b/packages/main/src/themes/ToggleButton.css index d0565805eb1e..0e4d782ef315 100644 --- a/packages/main/src/themes/ToggleButton.css +++ b/packages/main/src/themes/ToggleButton.css @@ -56,15 +56,15 @@ /* IE Specific CSS, duplicate it for ToggleButton */ -ui5-togglebutton[focused] { +[ui5-togglebutton][focused] { outline: none; } -ui5-togglebutton[focused] .ui5-button-root { +[ui5-togglebutton][focused] .ui5-button-root { position: relative; } -ui5-togglebutton[focused] .ui5-button-root::after { +[ui5-togglebutton][focused] .ui5-button-root::after { content: ""; position: absolute; border-width: 1px; @@ -76,31 +76,31 @@ ui5-togglebutton[focused] .ui5-button-root::after { right: var(--_ui5_button_focus_offset); } -ui5-togglebutton[active] .ui5-button-root::after { +[ui5-togglebutton][active] .ui5-button-root::after { border-color: var(--sapContent_ContrastFocusColor); } -ui5-togglebutton[design="Positive"][focused] .ui5-button-root::after { +[ui5-togglebutton][design="Positive"][focused] .ui5-button-root::after { border-color: var(--_ui5_button_positive_border_focus_hover_color); } -ui5-togglebutton[design="Positive"][active][focused] .ui5-button-root::after { +[ui5-togglebutton][design="Positive"][active][focused] .ui5-button-root::after { border-color: var(--sapContent_ContrastFocusColor); } -ui5-togglebutton[design="Negative"][focused] .ui5-button-root::after { +[ui5-togglebutton][design="Negative"][focused] .ui5-button-root::after { border-color: var(--_ui5_button_positive_border_focus_hover_color); } -ui5-togglebutton[design="Negative"][active][focused] .ui5-button-root::after { +[ui5-togglebutton][design="Negative"][active][focused] .ui5-button-root::after { border-color: var(--sapContent_ContrastFocusColor); } -ui5-togglebutton[design="Emphasized"][focused] .ui5-button-root::after { +[ui5-togglebutton][design="Emphasized"][focused] .ui5-button-root::after { border-color: var(--sapContent_ContrastFocusColor); } -ui5-togglebutton ui5-icon.ui5-button-icon { +[ui5-togglebutton] [ui5-icon].ui5-button-icon { height: var(--_ui5_button_icon_font_size); /* Center vertically all icons*/ top: 0; -} \ No newline at end of file +} diff --git a/packages/main/src/themes/Tokenizer.css b/packages/main/src/themes/Tokenizer.css index 0956360ac26a..c2e043a10bfb 100644 --- a/packages/main/src/themes/Tokenizer.css +++ b/packages/main/src/themes/Tokenizer.css @@ -62,6 +62,6 @@ justify-content: flex-end; } -::slotted(ui5-token) { +::slotted([ui5-token]) { margin-left: .25rem; -} \ No newline at end of file +} diff --git a/packages/main/test/pages/Button.html b/packages/main/test/pages/Button.html index 553fed99f651..8582d99e9190 100644 --- a/packages/main/test/pages/Button.html +++ b/packages/main/test/pages/Button.html @@ -29,7 +29,6 @@ -
- +
- + Cucumber Banana Tomato @@ -351,11 +351,11 @@ - + Wine - + Pop @@ -363,7 +363,7 @@ Dress - + Gravity @@ -403,7 +403,7 @@ SingleSelectBegin SingleSelectEnd MultiSelect - + Delete Expand Level 1 @@ -411,14 +411,14 @@ Expand All Collapse All - + - + @@ -431,10 +431,10 @@ - + - +
diff --git a/packages/tools/components-package/nps.js b/packages/tools/components-package/nps.js index 2e145269a1e0..31ee2fa45a6a 100644 --- a/packages/tools/components-package/nps.js +++ b/packages/tools/components-package/nps.js @@ -70,6 +70,20 @@ const getScripts = (options) => { run: "cross-env WDIO_LOG_LEVEL=error FORCE_COLOR=0 wdio config/wdio.conf.js", spec: "wdio run config/wdio.conf.js", }, + startWithScope: "nps scope.prepare scope.dev", + scope: { + prepare: "nps scope.lint prepare scope.testPages", + lint: `node "${LIB}/scoping/lint-src.js"`, + testPages: { + default: "nps scope.testPages.clean scope.testPages.copy scope.testPages.replace", + clean: "rimraf dist/test-resources/pages/scoped", + copy: `node "${LIB}/copy-and-watch/index.js" "dist/test-resources/pages/**/*" dist/test-resources/scoped`, + replace: `node "${LIB}/scoping/scope-test-pages.js" dist/test-resources/scoped demo`, + }, + dev: 'concurrently "nps serve" "nps scope.watch"', + watch: 'concurrently "nps watch.templates" "nps watch.samples" "nps watch.test" "nps watch.src" "nps scope.bundle" "nps watch.styles"', + bundle: "rollup --config config/rollup.config.js -w --environment ES5_BUILD,DEV,SCOPE" + } }; return scripts; diff --git a/packages/tools/components-package/rollup.js b/packages/tools/components-package/rollup.js index 61ea5ea4a91c..099f93029ede 100644 --- a/packages/tools/components-package/rollup.js +++ b/packages/tools/components-package/rollup.js @@ -81,9 +81,9 @@ const getPlugins = ({ transpile }) => { return plugins; }; -const getES6Config = () => { +const getES6Config = (input = "bundle.esm.js") => { return [{ - input: "bundle.esm.js", + input, output: { dir: "dist/resources", format: "esm", @@ -102,9 +102,9 @@ const getES6Config = () => { }]; }; -const getES5Config = () => { +const getES5Config = (input = "bundle.es5.js") => { return [ { - input: "bundle.es5.js", + input, output: { dir: "dist/resources", format: "iife", @@ -132,4 +132,14 @@ if (process.env.ES5_BUILD) { config = config.concat(getES5Config()); } +if (process.env.SCOPE) { + if (fs.existsSync("bundle.scoped.esm.js")) { + config = config.concat(getES6Config("bundle.scoped.esm.js")); + + if (fs.existsSync("bundle.scoped.es5.js") && process.env.ES5_BUILD) { + config = config.concat(getES5Config("bundle.scoped.es5.js")); + } + } +} + module.exports = config; diff --git a/packages/tools/lib/hbs2ui5/RenderTemplates/LitRenderer.js b/packages/tools/lib/hbs2ui5/RenderTemplates/LitRenderer.js index e6adc4788b6e..724d38f23981 100644 --- a/packages/tools/lib/hbs2ui5/RenderTemplates/LitRenderer.js +++ b/packages/tools/lib/hbs2ui5/RenderTemplates/LitRenderer.js @@ -2,9 +2,16 @@ const buildRenderer = (controlName, litTemplate) => { return ` /* eslint no-unused-vars: 0 */ import ifDefined from '@ui5/webcomponents-base/dist/renderer/ifDefined.js'; -import { html, svg, repeat, classMap, styleMap, unsafeHTML } from '@ui5/webcomponents-base/dist/renderer/LitRenderer.js'; +import { html, svg, repeat, classMap, styleMap, unsafeHTML, setTags, setSuffix } from '@ui5/webcomponents-base/dist/renderer/LitRenderer.js'; ${litTemplate} -export default block0;` + +const main = (context, tags, suffix) => { + setTags(tags); + setSuffix(suffix); + return block0(context); +}; + +export default main;` }; module.exports = { diff --git a/packages/tools/lib/init-package/index.js b/packages/tools/lib/init-package/index.js index fb12274ed951..9c7b6328b908 100644 --- a/packages/tools/lib/init-package/index.js +++ b/packages/tools/lib/init-package/index.js @@ -107,6 +107,10 @@ const updatePackageFile = () => { "prepublishOnly": "npm run build" }; + packageContent.ui5 = { + webComponentsPackage: true + }; + fs.writeFileSync("package.json", beautify(packageContent, null, 2, 100)); }; diff --git a/packages/tools/lib/scoping/get-all-tags.js b/packages/tools/lib/scoping/get-all-tags.js new file mode 100644 index 000000000000..394113ee8161 --- /dev/null +++ b/packages/tools/lib/scoping/get-all-tags.js @@ -0,0 +1,44 @@ +const fs = require("fs"); +const path = require("path"); +const glob = require("glob"); + +const getTag = file => { + const fileContent = String(fs.readFileSync(file)).replace(/\n/g, ""); + const matches = fileContent.match(/\btag\b:\s*\"(.*?)\"/); + return matches ? matches[1] : undefined; +}; + +const getAltTag = file => { + const fileContent = String(fs.readFileSync(file)).replace(/\n/g, ""); + const matches = fileContent.match(/\baltTag\b:\s*\"(.*?)\"/); + return matches ? matches[1] : undefined; +}; + +const getPackageTags = (packageDir) => { + const srcDir = path.join(packageDir, "src/"); + return glob.sync(path.join(srcDir, "/**/*.js")).flatMap(file => { + const tag = getTag(file); + const altTag = getAltTag(file); + return [tag, altTag]; + }).filter(item => !!item); +}; + +const isComponentsPackage = (packageFileContent) => { + return packageFileContent.ui5 && packageFileContent.ui5.webComponentsPackage; +}; + +const getDepComponentPackages = packageDir => { + const packageFile = path.join(packageDir, "package.json"); + const packageFileContent = JSON.parse(fs.readFileSync(packageFile)); + if (!isComponentsPackage(packageFileContent)) { + return []; + } + + return Object.keys(packageFileContent.dependencies || {}).map(dep => path.dirname(require.resolve(path.join(dep, "package.json")))); +}; + +const getAllTags = (packageDir) => { + return getPackageTags(packageDir).concat(getDepComponentPackages(packageDir).flatMap(getPackageTags)); +}; + +module.exports = getAllTags; diff --git a/packages/tools/lib/scoping/lint-src.js b/packages/tools/lib/scoping/lint-src.js new file mode 100644 index 000000000000..084101df38fe --- /dev/null +++ b/packages/tools/lib/scoping/lint-src.js @@ -0,0 +1,31 @@ +const fs = require("fs"); +const path = require("path"); +const glob = require("glob"); +const getAllTags = require("./get-all-tags.js"); + +const tags = getAllTags(process.cwd()); + +const errors = []; + +glob.sync(path.join(process.cwd(), "src/**/*.css")).forEach(file => { + let content = String(fs.readFileSync(file)); + tags.forEach(tag => { + if (content.match(new RegExp(`(^|[^\-_A-Za-z0-9"\[])(${tag})([^\-_A-Za-z0-9]|$)`, "g"))) { + errors.push(`Warning! ${tag} found in ${file}`); + } + }); +}); + +glob.sync(path.join(process.cwd(), "src/**/*.js")).forEach(file => { + let content = String(fs.readFileSync(file)); + tags.forEach(tag => { + if (content.match(new RegExp(`querySelector[A-Za-z]*..${tag}`, "g"))) { + errors.push(`Warning! querySelector for ${tag} found in ${file}`); + } + }); +}); + +if (errors.length) { + errors.forEach(error => console.log(error)); + throw new Error("Errors found."); +} diff --git a/packages/tools/lib/scoping/scope-test-pages.js b/packages/tools/lib/scoping/scope-test-pages.js new file mode 100644 index 000000000000..ff1ccaf9dbbc --- /dev/null +++ b/packages/tools/lib/scoping/scope-test-pages.js @@ -0,0 +1,40 @@ +const fs = require("fs"); +const path = require("path"); +const glob = require("glob"); +const getAllTags = require("./get-all-tags.js"); + +const root = process.argv[2]; +const suffix = process.argv[3]; + +const tags = getAllTags(process.cwd()); + +// Replaces tags in HTML content, f.e. with or with +const replaceTagsHTML = content => { + tags.forEach(tag => { + content = content.replace(new RegExp(`(<\/?)(${tag})(\/?[> \t\n])`, "g"), `$1$2-${suffix}$3`); + }); + return content; +}; + +// Replace tags in any content +const replaceTagsAny = content => { + tags.forEach(tag => { + content = content.replace(new RegExp(`(^|[^\-_A-Za-z0-9])(${tag})([^\-_A-Za-z0-9]|$)`, "g"), `$1$2-${suffix}$3`); + }); + return content; +}; + +// Replace bundle names and HTML tag names in test pages +glob.sync(path.join(root, "/**/*.html")).forEach(file => { + let content = String(fs.readFileSync(file)); + content = content.replace(/bundle\.(.*?)\.js/g, `bundle.scoped.$1.js`); + content = replaceTagsHTML(content); + fs.writeFileSync(file, content); +}); + +// Replace tag names everywhere +glob.sync(path.join(root, "/**/*.{html,css,js}")).forEach(file => { + let content = String(fs.readFileSync(file)); + content = replaceTagsAny(content); + fs.writeFileSync(file, content); +});