@ui5/webcomponents-base 0.0.0-dff5837d7 → 0.0.0-ec448881d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +3 -0
- package/CHANGELOG.md +336 -0
- package/README.md +26 -2
- package/bundle.esm.js +16 -7
- package/dist/AssetRegistry.js +8 -7
- package/dist/Boot.js +59 -0
- package/dist/CSP.js +59 -0
- package/dist/CustomElementsRegistry.js +60 -4
- package/dist/CustomElementsScope.js +30 -0
- package/dist/CustomElementsScopeUtils.js +108 -0
- package/dist/DOMObserver.js +65 -0
- package/dist/Device.js +71 -773
- package/dist/EventProvider.js +30 -26
- package/dist/FeaturesRegistry.js +4 -1
- package/dist/FontFace.js +19 -62
- package/dist/InitialConfiguration.js +43 -8
- package/dist/Keys.js +125 -0
- package/dist/ManagedStyles.js +83 -0
- package/dist/MediaRange.js +109 -0
- package/dist/{util/parseProperties.js → PropertiesFileFormat.js} +6 -0
- package/dist/Render.js +175 -0
- package/dist/RenderQueue.js +41 -17
- package/dist/RenderScheduler.js +24 -158
- package/dist/Runtimes.js +107 -0
- package/dist/StaticArea.js +1 -39
- package/dist/StaticAreaItem.js +58 -62
- package/dist/SystemCSSVars.js +4 -25
- package/dist/Theming.js +2 -1
- package/dist/UI5Element.js +391 -350
- package/dist/UI5ElementMetadata.js +158 -18
- package/dist/asset-registries/Icons.js +117 -13
- package/dist/asset-registries/Illustrations.js +30 -0
- package/dist/asset-registries/LocaleData.js +105 -66
- package/dist/asset-registries/Themes.js +29 -34
- package/dist/asset-registries/i18n.js +63 -48
- package/dist/assets-meta/IconCollectionsAlias.js +18 -0
- package/dist/config/AnimationMode.js +11 -1
- package/dist/config/Icons.js +52 -0
- package/dist/config/Language.js +33 -6
- package/dist/config/Theme.js +25 -0
- package/dist/css/BusyIndicator.css +80 -0
- package/dist/css/FontFace.css +75 -0
- package/dist/css/OverrideFontFace.css +32 -0
- package/dist/css/SystemCSSVars.css +17 -0
- package/dist/delegate/ItemNavigation.js +239 -170
- package/dist/delegate/ResizeHandler.js +78 -37
- package/dist/delegate/ScrollEnablement.js +49 -20
- package/dist/features/F6Navigation.js +106 -0
- package/dist/features/OpenUI5Enablement.js +119 -0
- package/dist/features/OpenUI5Support.js +42 -7
- package/dist/generated/AssetParameters.js +1 -1
- package/dist/generated/VersionInfo.js +10 -0
- package/dist/generated/css/BusyIndicator.css.js +5 -0
- package/dist/generated/css/FontFace.css.js +5 -0
- package/dist/generated/css/OverrideFontFace.css.js +5 -0
- package/dist/generated/css/SystemCSSVars.css.js +5 -0
- package/dist/getSharedResource.js +30 -0
- package/dist/i18nBundle.js +58 -5
- package/dist/isLegacyBrowser.js +3 -0
- package/dist/locale/applyDirection.js +6 -4
- package/dist/locale/directionChange.js +32 -0
- package/dist/locale/getEffectiveDir.js +28 -0
- package/dist/locale/getLocale.js +12 -2
- package/dist/locale/languageChange.js +1 -1
- package/dist/renderer/LitRenderer.js +44 -7
- package/dist/renderer/directives/style-map.js +72 -0
- package/dist/renderer/executeTemplate.js +34 -0
- package/dist/resources/bundle.esm.js +15 -112
- package/dist/resources/bundle.esm.js.map +1 -1
- package/dist/sap/base/Log.js +241 -0
- package/dist/sap/base/assert.js +8 -0
- package/dist/sap/base/security/URLListValidator.js +148 -0
- package/dist/sap/base/security/encodeCSS.js +14 -0
- package/dist/sap/base/security/encodeXML.js +23 -0
- package/dist/sap/base/security/sanitizeHTML.js +16 -0
- package/dist/sap/base/strings/toHex.js +8 -0
- package/dist/sap/base/util/now.js +7 -0
- package/dist/sap/ui/thirdparty/caja-html-sanitizer.js +3585 -0
- package/dist/test-resources/assets/Themes.js +10 -6
- package/dist/test-resources/elements/Parent.js +6 -2
- package/dist/test-resources/elements/WithStaticArea.js +2 -1
- package/dist/test-resources/pages/AllTestElements.html +3 -3
- package/dist/test-resources/pages/Configuration.html +0 -2
- package/dist/test-resources/pages/ConfigurationScript.html +0 -2
- package/dist/test-resources/pages/assets/messagebundle_de.properties +1 -0
- package/dist/test-resources/pages/assets/messagebundle_en.properties +1 -0
- package/dist/test-resources/pages/assets/messagebundle_es.properties +1 -0
- package/dist/test-resources/pages/assets/messagebundle_fr.properties +1 -0
- package/dist/test-resources/pages/i18n.html +33 -0
- package/dist/test-resources/specs/ConfigurationChange.spec.js +10 -8
- package/dist/test-resources/specs/ConfigurationScript.spec.js +25 -23
- package/dist/test-resources/specs/ConfigurationURL.spec.js +65 -17
- package/dist/test-resources/specs/CustomTheme.spec.js +9 -7
- package/dist/test-resources/specs/EventProvider.spec.js +63 -0
- package/dist/test-resources/specs/StaticArea.spec.js +56 -12
- package/dist/test-resources/specs/Theming.spec.js +23 -10
- package/dist/test-resources/specs/UI5ElementInvalidation.js +54 -70
- package/dist/test-resources/specs/UI5ElementLifecycle.js +19 -14
- package/dist/test-resources/specs/UI5ElementListenForChildPropChanges.spec.js +25 -51
- package/dist/test-resources/specs/UI5ElementMetadataExt.js +9 -7
- package/dist/test-resources/specs/UI5ElementPropertyValidation.js +7 -5
- package/dist/test-resources/specs/UI5ElementPropsAndAttrs.spec.js +37 -35
- package/dist/test-resources/specs/UI5ElementShadowDOM.js +10 -8
- package/dist/test-resources/specs/UI5ElementSlots.js +10 -8
- package/dist/theming/CustomStyle.js +47 -6
- package/dist/theming/ThemeLoaded.js +22 -0
- package/dist/theming/applyTheme.js +13 -15
- package/dist/theming/getConstructableStyle.js +15 -10
- package/dist/theming/getEffectiveLinksHrefs.js +27 -0
- package/dist/theming/getEffectiveStyle.js +32 -8
- package/dist/theming/getStylesString.js +15 -0
- package/dist/theming/getThemeDesignerTheme.js +25 -5
- package/dist/theming/preloadLinks.js +23 -0
- package/dist/types/CSSColor.js +9 -0
- package/dist/types/CalendarType.js +1 -1
- package/dist/types/DataType.js +13 -1
- package/dist/types/Float.js +4 -0
- package/dist/types/Integer.js +4 -0
- package/dist/types/InvisibleMessageMode.js +30 -0
- package/dist/types/ItemNavigationBehavior.js +2 -7
- package/dist/types/PopupState.js +1 -1
- package/dist/types/ValueState.js +1 -1
- package/dist/updateShadowRoot.js +30 -0
- package/dist/util/AriaLabelHelper.js +41 -0
- package/dist/util/Caret.js +45 -0
- package/dist/util/ColorConversion.js +370 -0
- package/dist/util/FocusableElements.js +22 -9
- package/dist/util/HTMLSanitizer.js +7 -0
- package/dist/util/InvisibleMessage.js +60 -0
- package/dist/util/PopupUtils.js +93 -0
- package/dist/util/SlotsHelper.js +43 -0
- package/dist/util/TabbableElements.js +5 -1
- package/dist/util/arraysAreEqual.js +15 -0
- package/dist/util/clamp.js +12 -0
- package/dist/util/createLinkInHead.js +19 -0
- package/dist/util/debounce.js +17 -0
- package/dist/util/escapeRegex.js +10 -0
- package/dist/util/generateHighlightedMarkup.js +42 -0
- package/dist/util/getActiveElement.js +11 -0
- package/dist/util/getClassCopy.js +10 -0
- package/dist/util/getEffectiveContentDensity.js +5 -0
- package/dist/util/getNormalizedTarget.js +16 -0
- package/dist/util/getSingletonElementInstance.js +13 -0
- package/dist/util/isElementInView.js +15 -0
- package/dist/util/isNodeHidden.js +1 -1
- package/dist/util/isNodeTabbable.js +4 -4
- package/dist/util/isValidPropertyName.js +6 -5
- package/hash.txt +1 -0
- package/index.js +1 -1
- package/lib/generate-asset-parameters/index.js +8 -5
- package/lib/generate-styles/index.js +26 -0
- package/lib/generate-version-info/index.js +32 -0
- package/package-scripts.js +30 -19
- package/package.json +19 -13
- package/src/AssetRegistry.js +8 -7
- package/src/Boot.js +59 -0
- package/src/CSP.js +59 -0
- package/src/CustomElementsRegistry.js +60 -4
- package/src/CustomElementsScope.js +30 -0
- package/src/CustomElementsScopeUtils.js +108 -0
- package/src/DOMObserver.js +65 -0
- package/src/Device.js +71 -773
- package/src/EventProvider.js +30 -26
- package/src/FeaturesRegistry.js +4 -1
- package/src/FontFace.js +19 -62
- package/src/InitialConfiguration.js +43 -8
- package/src/Keys.js +125 -0
- package/src/ManagedStyles.js +83 -0
- package/src/MediaRange.js +109 -0
- package/src/{util/parseProperties.js → PropertiesFileFormat.js} +6 -0
- package/src/Render.js +175 -0
- package/src/RenderQueue.js +41 -17
- package/src/RenderScheduler.js +24 -158
- package/src/Runtimes.js +107 -0
- package/src/StaticArea.js +1 -39
- package/src/StaticAreaItem.js +58 -62
- package/src/SystemCSSVars.js +4 -25
- package/src/Theming.js +2 -1
- package/src/UI5Element.js +391 -350
- package/src/UI5ElementMetadata.js +158 -18
- package/src/asset-registries/Icons.js +117 -13
- package/src/asset-registries/Illustrations.js +30 -0
- package/src/asset-registries/LocaleData.js +105 -66
- package/src/asset-registries/Themes.js +29 -34
- package/src/asset-registries/i18n.js +63 -48
- package/src/assets-meta/IconCollectionsAlias.js +18 -0
- package/src/config/AnimationMode.js +11 -1
- package/src/config/Icons.js +52 -0
- package/src/config/Language.js +33 -6
- package/src/config/Theme.js +25 -0
- package/src/css/BusyIndicator.css +80 -0
- package/src/css/FontFace.css +75 -0
- package/src/css/OverrideFontFace.css +32 -0
- package/src/css/SystemCSSVars.css +17 -0
- package/src/delegate/ItemNavigation.js +239 -170
- package/src/delegate/ResizeHandler.js +78 -37
- package/src/delegate/ScrollEnablement.js +49 -20
- package/src/features/F6Navigation.js +106 -0
- package/src/features/OpenUI5Enablement.js +119 -0
- package/src/features/OpenUI5Support.js +42 -7
- package/src/getSharedResource.js +30 -0
- package/src/i18nBundle.js +58 -5
- package/src/isLegacyBrowser.js +3 -0
- package/src/locale/applyDirection.js +6 -4
- package/src/locale/directionChange.js +32 -0
- package/src/locale/getEffectiveDir.js +28 -0
- package/src/locale/getLocale.js +12 -2
- package/src/locale/languageChange.js +1 -1
- package/src/renderer/LitRenderer.js +44 -7
- package/src/renderer/directives/style-map.js +72 -0
- package/src/renderer/executeTemplate.js +34 -0
- package/src/theming/CustomStyle.js +47 -6
- package/src/theming/ThemeLoaded.js +22 -0
- package/src/theming/applyTheme.js +13 -15
- package/src/theming/getConstructableStyle.js +15 -10
- package/src/theming/getEffectiveLinksHrefs.js +27 -0
- package/src/theming/getEffectiveStyle.js +32 -8
- package/src/theming/getStylesString.js +15 -0
- package/src/theming/getThemeDesignerTheme.js +25 -5
- package/src/theming/preloadLinks.js +23 -0
- package/src/types/CSSColor.js +9 -0
- package/src/types/CalendarType.js +1 -1
- package/src/types/DataType.js +13 -1
- package/src/types/Float.js +4 -0
- package/src/types/Integer.js +4 -0
- package/src/types/InvisibleMessageMode.js +30 -0
- package/src/types/ItemNavigationBehavior.js +2 -7
- package/src/types/PopupState.js +1 -1
- package/src/types/ValueState.js +1 -1
- package/src/updateShadowRoot.js +30 -0
- package/src/util/AriaLabelHelper.js +41 -0
- package/src/util/Caret.js +45 -0
- package/src/util/ColorConversion.js +370 -0
- package/src/util/FocusableElements.js +22 -9
- package/src/util/HTMLSanitizer.js +7 -0
- package/src/util/InvisibleMessage.js +60 -0
- package/src/util/PopupUtils.js +93 -0
- package/src/util/SlotsHelper.js +43 -0
- package/src/util/TabbableElements.js +5 -1
- package/src/util/arraysAreEqual.js +15 -0
- package/src/util/clamp.js +12 -0
- package/src/util/createLinkInHead.js +19 -0
- package/src/util/debounce.js +17 -0
- package/src/util/escapeRegex.js +10 -0
- package/src/util/generateHighlightedMarkup.js +42 -0
- package/src/util/getActiveElement.js +11 -0
- package/src/util/getClassCopy.js +10 -0
- package/src/util/getEffectiveContentDensity.js +5 -0
- package/src/util/getNormalizedTarget.js +16 -0
- package/src/util/getSingletonElementInstance.js +13 -0
- package/src/util/isElementInView.js +15 -0
- package/src/util/isNodeHidden.js +1 -1
- package/src/util/isNodeTabbable.js +4 -4
- package/src/util/isValidPropertyName.js +6 -5
- package/used-modules.txt +10 -0
- package/bundle.es5.js +0 -28
- package/dist/SVGIconRegistry.js +0 -60
- package/dist/boot.js +0 -34
- package/dist/compatibility/DOMObserver.js +0 -62
- package/dist/compatibility/patchNodeValue.js +0 -24
- package/dist/compatibility/whenPolyfillLoaded.js +0 -26
- package/dist/delegate/CustomResize.js +0 -78
- package/dist/delegate/NativeResize.js +0 -44
- package/dist/features/PropertiesFormatSupport.js +0 -8
- package/dist/features/browsersupport/Edge.js +0 -6
- package/dist/features/browsersupport/IE11.js +0 -41
- package/dist/features/browsersupport/IE11WithWebComponentsPolyfill.js +0 -5
- package/dist/renderer/ifDefined.js +0 -21
- package/dist/resources/bundle.es5.js +0 -212
- package/dist/resources/bundle.es5.js.map +0 -1
- package/dist/theming/CSSVarsPonyfill.js +0 -24
- package/dist/theming/adaptCSSForIE.js +0 -90
- package/dist/theming/createComponentStyleTag.js +0 -49
- package/dist/theming/createThemePropertiesStyleTag.js +0 -20
- package/dist/thirdparty/Array.from.js +0 -16
- package/dist/thirdparty/Array.prototype.fill.js +0 -44
- package/dist/thirdparty/Array.prototype.find.js +0 -46
- package/dist/thirdparty/Array.prototype.includes.js +0 -51
- package/dist/thirdparty/Element.prototype.closest.js +0 -11
- package/dist/thirdparty/Element.prototype.matches.js +0 -6
- package/dist/thirdparty/Map.prototype.keys.js +0 -9
- package/dist/thirdparty/Number.isInteger.js +0 -5
- package/dist/thirdparty/Number.isNaN.js +0 -1
- package/dist/thirdparty/Number.parseInt.js +0 -1
- package/dist/thirdparty/Object.assign.js +0 -31
- package/dist/thirdparty/Object.entries.js +0 -11
- package/dist/thirdparty/Symbol.js +0 -2
- package/dist/thirdparty/WeakSet.js +0 -27
- package/dist/thirdparty/es6-string-methods.js +0 -182
- package/dist/thirdparty/events-polyfills.js +0 -89
- package/dist/thirdparty/fetch.js +0 -1
- package/dist/thirdparty/template.js +0 -600
- package/dist/thirdparty/webcomponents-sd-ce-pf.js +0 -318
- package/dist/util/isSlot.js +0 -3
- package/dist/webcomponentsjs/LICENSE.md +0 -19
- package/dist/webcomponentsjs/README.md +0 -229
- package/dist/webcomponentsjs/bundles/webcomponents-ce.js +0 -63
- package/dist/webcomponentsjs/bundles/webcomponents-ce.js.map +0 -1
- package/dist/webcomponentsjs/bundles/webcomponents-sd-ce-pf.js +0 -297
- package/dist/webcomponentsjs/bundles/webcomponents-sd-ce-pf.js.map +0 -1
- package/dist/webcomponentsjs/bundles/webcomponents-sd-ce.js +0 -208
- package/dist/webcomponentsjs/bundles/webcomponents-sd-ce.js.map +0 -1
- package/dist/webcomponentsjs/bundles/webcomponents-sd.js +0 -166
- package/dist/webcomponentsjs/bundles/webcomponents-sd.js.map +0 -1
- package/dist/webcomponentsjs/custom-elements-es5-adapter.js +0 -15
- package/dist/webcomponentsjs/package.json +0 -46
- package/dist/webcomponentsjs/src/entrypoints/custom-elements-es5-adapter-index.js +0 -16
- package/dist/webcomponentsjs/src/entrypoints/webcomponents-bundle-index.js +0 -53
- package/dist/webcomponentsjs/src/entrypoints/webcomponents-ce-index.js +0 -17
- package/dist/webcomponentsjs/src/entrypoints/webcomponents-sd-ce-index.js +0 -19
- package/dist/webcomponentsjs/src/entrypoints/webcomponents-sd-ce-pf-index.js +0 -28
- package/dist/webcomponentsjs/src/entrypoints/webcomponents-sd-index.js +0 -18
- package/dist/webcomponentsjs/webcomponents-bundle.js +0 -298
- package/dist/webcomponentsjs/webcomponents-bundle.js.map +0 -1
- package/dist/webcomponentsjs/webcomponents-loader.js +0 -185
- package/src/SVGIconRegistry.js +0 -60
- package/src/boot.js +0 -34
- package/src/compatibility/DOMObserver.js +0 -62
- package/src/compatibility/patchNodeValue.js +0 -24
- package/src/compatibility/whenPolyfillLoaded.js +0 -26
- package/src/delegate/CustomResize.js +0 -78
- package/src/delegate/NativeResize.js +0 -44
- package/src/features/PropertiesFormatSupport.js +0 -8
- package/src/features/browsersupport/Edge.js +0 -6
- package/src/features/browsersupport/IE11.js +0 -41
- package/src/features/browsersupport/IE11WithWebComponentsPolyfill.js +0 -5
- package/src/renderer/ifDefined.js +0 -21
- package/src/theming/CSSVarsPonyfill.js +0 -24
- package/src/theming/adaptCSSForIE.js +0 -90
- package/src/theming/createComponentStyleTag.js +0 -49
- package/src/theming/createThemePropertiesStyleTag.js +0 -20
- package/src/thirdparty/Array.from.js +0 -16
- package/src/thirdparty/Array.prototype.fill.js +0 -44
- package/src/thirdparty/Array.prototype.find.js +0 -46
- package/src/thirdparty/Array.prototype.includes.js +0 -51
- package/src/thirdparty/Element.prototype.closest.js +0 -11
- package/src/thirdparty/Element.prototype.matches.js +0 -6
- package/src/thirdparty/Map.prototype.keys.js +0 -9
- package/src/thirdparty/Number.isInteger.js +0 -5
- package/src/thirdparty/Number.isNaN.js +0 -1
- package/src/thirdparty/Number.parseInt.js +0 -1
- package/src/thirdparty/Object.assign.js +0 -31
- package/src/thirdparty/Object.entries.js +0 -11
- package/src/thirdparty/Symbol.js +0 -2
- package/src/thirdparty/WeakSet.js +0 -27
- package/src/thirdparty/es6-string-methods.js +0 -182
- package/src/thirdparty/events-polyfills.js +0 -89
- package/src/thirdparty/fetch.js +0 -1
- package/src/thirdparty/template.js +0 -600
- package/src/thirdparty/webcomponents-sd-ce-pf.js +0 -318
- package/src/util/isSlot.js +0 -3
package/dist/UI5Element.js
CHANGED
|
@@ -1,34 +1,52 @@
|
|
|
1
1
|
import merge from "./thirdparty/merge.js";
|
|
2
|
-
import boot from "./
|
|
2
|
+
import { boot } from "./Boot.js";
|
|
3
3
|
import UI5ElementMetadata from "./UI5ElementMetadata.js";
|
|
4
|
+
import EventProvider from "./EventProvider.js";
|
|
5
|
+
import getSingletonElementInstance from "./util/getSingletonElementInstance.js";
|
|
4
6
|
import StaticAreaItem from "./StaticAreaItem.js";
|
|
5
|
-
import
|
|
7
|
+
import updateShadowRoot from "./updateShadowRoot.js";
|
|
8
|
+
import { renderDeferred, renderImmediately, cancelRender } from "./Render.js";
|
|
6
9
|
import { registerTag, isTagRegistered, recordTagRegistrationFailure } from "./CustomElementsRegistry.js";
|
|
7
|
-
import
|
|
10
|
+
import { observeDOMNode, unobserveDOMNode } from "./DOMObserver.js";
|
|
8
11
|
import { skipOriginalEvent } from "./config/NoConflict.js";
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import createComponentStyleTag from "./theming/createComponentStyleTag.js";
|
|
12
|
-
import getEffectiveStyle from "./theming/getEffectiveStyle.js";
|
|
13
|
-
import Integer from "./types/Integer.js";
|
|
14
|
-
import Float from "./types/Float.js";
|
|
12
|
+
import getEffectiveDir from "./locale/getEffectiveDir.js";
|
|
13
|
+
import DataType from "./types/DataType.js";
|
|
15
14
|
import { kebabToCamelCase, camelToKebabCase } from "./util/StringHelper.js";
|
|
16
15
|
import isValidPropertyName from "./util/isValidPropertyName.js";
|
|
17
|
-
import
|
|
16
|
+
import isDescendantOf from "./util/isDescendantOf.js";
|
|
17
|
+
import { isSlot, getSlotName, getSlottedElementsList } from "./util/SlotsHelper.js";
|
|
18
|
+
import arraysAreEqual from "./util/arraysAreEqual.js";
|
|
19
|
+
import getClassCopy from "./util/getClassCopy.js";
|
|
18
20
|
import { markAsRtlAware } from "./locale/RTLAwareRegistry.js";
|
|
19
|
-
|
|
20
|
-
const metadata = {
|
|
21
|
-
events: {
|
|
22
|
-
"_property-change": {},
|
|
23
|
-
},
|
|
24
|
-
};
|
|
21
|
+
import preloadLinks from "./theming/preloadLinks.js";
|
|
25
22
|
|
|
26
23
|
let autoId = 0;
|
|
27
24
|
|
|
28
25
|
const elementTimeouts = new Map();
|
|
26
|
+
const uniqueDependenciesCache = new Map();
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Triggers re-rendering of a UI5Element instance due to state change.
|
|
30
|
+
*
|
|
31
|
+
* @param changeInfo An object with information about the change that caused invalidation.
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
function _invalidate(changeInfo) {
|
|
35
|
+
// Invalidation should be suppressed: 1) before the component is rendered for the first time 2) and during the execution of onBeforeRendering
|
|
36
|
+
// This is necessary not only as an optimization, but also to avoid infinite loops on invalidation between children and parents (when invalidateOnChildChange is used)
|
|
37
|
+
if (this._suppressInvalidation) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
29
40
|
|
|
30
|
-
|
|
31
|
-
|
|
41
|
+
// Call the onInvalidation hook
|
|
42
|
+
this.onInvalidation(changeInfo);
|
|
43
|
+
|
|
44
|
+
this._changedState.push(changeInfo);
|
|
45
|
+
renderDeferred(this);
|
|
46
|
+
this._eventProvider.fireEvent("invalidate", { ...changeInfo, target: this });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let metadata = {};
|
|
32
50
|
|
|
33
51
|
/**
|
|
34
52
|
* Base class for all UI5 Web Components
|
|
@@ -43,19 +61,26 @@ const GLOBAL_DIR_CSS_VAR = "--_ui5_dir";
|
|
|
43
61
|
class UI5Element extends HTMLElement {
|
|
44
62
|
constructor() {
|
|
45
63
|
super();
|
|
46
|
-
this._initializeState();
|
|
47
|
-
this._upgradeAllProperties();
|
|
48
|
-
this._initializeContainers();
|
|
49
|
-
this._upToDate = false;
|
|
50
64
|
|
|
65
|
+
this._changedState = []; // Filled on each invalidation, cleared on re-render (used for debugging)
|
|
66
|
+
this._suppressInvalidation = true; // A flag telling whether all invalidations should be ignored. Initialized with "true" because a UI5Element can not be invalidated until it is rendered for the first time
|
|
67
|
+
this._inDOM = false; // A flag telling whether the UI5Element is currently in the DOM tree of the document or not
|
|
68
|
+
this._fullyConnected = false; // A flag telling whether the UI5Element's onEnterDOM hook was called (since it's possible to have the element removed from DOM before that)
|
|
69
|
+
this._childChangeListeners = new Map(); // used to store lazy listeners per slot for the child change event of every child inside that slot
|
|
70
|
+
this._slotChangeListeners = new Map(); // used to store lazy listeners per slot for the slotchange event of all slot children inside that slot
|
|
71
|
+
this._eventProvider = new EventProvider(); // used by parent components for listening to changes to child components
|
|
51
72
|
let deferredResolve;
|
|
52
73
|
this._domRefReadyPromise = new Promise(resolve => {
|
|
53
74
|
deferredResolve = resolve;
|
|
54
75
|
});
|
|
55
76
|
this._domRefReadyPromise._deferredResolve = deferredResolve;
|
|
56
77
|
|
|
57
|
-
this.
|
|
58
|
-
this.
|
|
78
|
+
this._initializeState();
|
|
79
|
+
this._upgradeAllProperties();
|
|
80
|
+
|
|
81
|
+
if (this.constructor._needsShadowDOM()) {
|
|
82
|
+
this.attachShadow({ mode: "open" });
|
|
83
|
+
}
|
|
59
84
|
}
|
|
60
85
|
|
|
61
86
|
/**
|
|
@@ -73,60 +98,34 @@ class UI5Element extends HTMLElement {
|
|
|
73
98
|
}
|
|
74
99
|
|
|
75
100
|
/**
|
|
101
|
+
* Do not call this method from derivatives of UI5Element, use "onEnterDOM" only
|
|
76
102
|
* @private
|
|
77
103
|
*/
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
104
|
+
async connectedCallback() {
|
|
105
|
+
this.setAttribute(this.constructor.getMetadata().getPureTag(), "");
|
|
106
|
+
if (this.constructor.getMetadata().supportsF6FastNavigation()) {
|
|
107
|
+
this.setAttribute("data-sap-ui-fastnavgroup", "true");
|
|
108
|
+
}
|
|
81
109
|
|
|
82
|
-
|
|
83
|
-
if (needsShadowDOM) {
|
|
84
|
-
this.attachShadow({ mode: "open" });
|
|
110
|
+
const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
|
|
85
111
|
|
|
86
|
-
|
|
87
|
-
if (window.ShadyDOM) {
|
|
88
|
-
createComponentStyleTag(this.constructor);
|
|
89
|
-
}
|
|
112
|
+
this._inDOM = true;
|
|
90
113
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
114
|
+
if (slotsAreManaged) {
|
|
115
|
+
// always register the observer before yielding control to the main thread (await)
|
|
116
|
+
this._startObservingDOMChildren();
|
|
117
|
+
await this._processChildren();
|
|
96
118
|
}
|
|
97
119
|
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
this.staticAreaItem = new StaticAreaItem(this);
|
|
120
|
+
if (!this._inDOM) { // Component removed from DOM while _processChildren was running
|
|
121
|
+
return;
|
|
101
122
|
}
|
|
102
|
-
}
|
|
103
123
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const needsShadowDOM = this.constructor._needsShadowDOM();
|
|
110
|
-
const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
|
|
111
|
-
|
|
112
|
-
// Render the Shadow DOM
|
|
113
|
-
if (needsShadowDOM) {
|
|
114
|
-
if (slotsAreManaged) {
|
|
115
|
-
// always register the observer before yielding control to the main thread (await)
|
|
116
|
-
this._startObservingDOMChildren();
|
|
117
|
-
await this._processChildren();
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (!this.shadowRoot) { // Workaround for Firefox74 bug
|
|
121
|
-
await Promise.resolve();
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
RenderScheduler.register(this);
|
|
125
|
-
await RenderScheduler.renderImmediately(this);
|
|
126
|
-
this._domRefReadyPromise._deferredResolve();
|
|
127
|
-
if (typeof this.onEnterDOM === "function") {
|
|
128
|
-
this.onEnterDOM();
|
|
129
|
-
}
|
|
124
|
+
renderImmediately(this);
|
|
125
|
+
this._domRefReadyPromise._deferredResolve();
|
|
126
|
+
this._fullyConnected = true;
|
|
127
|
+
if (typeof this.onEnterDOM === "function") {
|
|
128
|
+
this.onEnterDOM();
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
131
|
|
|
@@ -135,24 +134,26 @@ class UI5Element extends HTMLElement {
|
|
|
135
134
|
* @private
|
|
136
135
|
*/
|
|
137
136
|
disconnectedCallback() {
|
|
138
|
-
const needsShadowDOM = this.constructor._needsShadowDOM();
|
|
139
|
-
const needsStaticArea = this.constructor._needsStaticArea();
|
|
140
137
|
const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
|
|
141
138
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
139
|
+
this._inDOM = false;
|
|
140
|
+
|
|
141
|
+
if (slotsAreManaged) {
|
|
142
|
+
this._stopObservingDOMChildren();
|
|
143
|
+
}
|
|
146
144
|
|
|
147
|
-
|
|
145
|
+
if (this._fullyConnected) {
|
|
148
146
|
if (typeof this.onExitDOM === "function") {
|
|
149
147
|
this.onExitDOM();
|
|
150
148
|
}
|
|
149
|
+
this._fullyConnected = false;
|
|
151
150
|
}
|
|
152
151
|
|
|
153
|
-
if (
|
|
154
|
-
this.staticAreaItem.
|
|
152
|
+
if (this.staticAreaItem && this.staticAreaItem.parentElement) {
|
|
153
|
+
this.staticAreaItem.parentElement.removeChild(this.staticAreaItem);
|
|
155
154
|
}
|
|
155
|
+
|
|
156
|
+
cancelRender(this);
|
|
156
157
|
}
|
|
157
158
|
|
|
158
159
|
/**
|
|
@@ -168,16 +169,16 @@ class UI5Element extends HTMLElement {
|
|
|
168
169
|
const mutationObserverOptions = {
|
|
169
170
|
childList: true,
|
|
170
171
|
subtree: canSlotText,
|
|
171
|
-
characterData:
|
|
172
|
+
characterData: canSlotText,
|
|
172
173
|
};
|
|
173
|
-
|
|
174
|
+
observeDOMNode(this, this._processChildren.bind(this), mutationObserverOptions);
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
/**
|
|
177
178
|
* @private
|
|
178
179
|
*/
|
|
179
180
|
_stopObservingDOMChildren() {
|
|
180
|
-
|
|
181
|
+
unobserveDOMNode(this);
|
|
181
182
|
}
|
|
182
183
|
|
|
183
184
|
/**
|
|
@@ -199,8 +200,14 @@ class UI5Element extends HTMLElement {
|
|
|
199
200
|
const canSlotText = this.constructor.getMetadata().canSlotText();
|
|
200
201
|
const domChildren = Array.from(canSlotText ? this.childNodes : this.children);
|
|
201
202
|
|
|
202
|
-
//
|
|
203
|
+
const slotsCachedContentMap = new Map(); // Store here the content of each slot before the mutation occurred
|
|
204
|
+
const propertyNameToSlotMap = new Map(); // Used for reverse lookup to determine to which slot the property name corresponds
|
|
205
|
+
|
|
206
|
+
// Init the _state object based on the supported slots and store the previous values
|
|
203
207
|
for (const [slotName, slotData] of Object.entries(slotsMap)) { // eslint-disable-line
|
|
208
|
+
const propertyName = slotData.propertyName || slotName;
|
|
209
|
+
propertyNameToSlotMap.set(propertyName, slotName);
|
|
210
|
+
slotsCachedContentMap.set(propertyName, [...this._state[propertyName]]);
|
|
204
211
|
this._clearSlot(slotName, slotData);
|
|
205
212
|
}
|
|
206
213
|
|
|
@@ -209,7 +216,7 @@ class UI5Element extends HTMLElement {
|
|
|
209
216
|
|
|
210
217
|
const allChildrenUpgraded = domChildren.map(async (child, idx) => {
|
|
211
218
|
// Determine the type of the child (mainly by the slot attribute)
|
|
212
|
-
const slotName =
|
|
219
|
+
const slotName = getSlotName(child);
|
|
213
220
|
const slotData = slotsMap[slotName];
|
|
214
221
|
|
|
215
222
|
// Check if the slotName is supported
|
|
@@ -247,12 +254,15 @@ class UI5Element extends HTMLElement {
|
|
|
247
254
|
|
|
248
255
|
child = this.constructor.getMetadata().constructor.validateSlotValue(child, slotData);
|
|
249
256
|
|
|
250
|
-
if (
|
|
251
|
-
|
|
257
|
+
// Listen for any invalidation on the child if invalidateOnChildChange is true or an object (ignore when false or not set)
|
|
258
|
+
if (child.isUI5Element && slotData.invalidateOnChildChange) {
|
|
259
|
+
const method = (child.attachInvalidate || child._attachChange).bind(child);
|
|
260
|
+
method(this._getChildChangeListener(slotName));
|
|
252
261
|
}
|
|
253
262
|
|
|
263
|
+
// Listen for the slotchange event if the child is a slot itself
|
|
254
264
|
if (isSlot(child)) {
|
|
255
|
-
this._attachSlotChange(child);
|
|
265
|
+
this._attachSlotChange(child, slotName);
|
|
256
266
|
}
|
|
257
267
|
|
|
258
268
|
const propertyName = slotData.propertyName || slotName;
|
|
@@ -268,10 +278,33 @@ class UI5Element extends HTMLElement {
|
|
|
268
278
|
|
|
269
279
|
// Distribute the child in the _state object, keeping the Light DOM order,
|
|
270
280
|
// not the order elements are defined.
|
|
271
|
-
slottedChildrenMap.forEach((children,
|
|
272
|
-
this._state[
|
|
281
|
+
slottedChildrenMap.forEach((children, propertyName) => {
|
|
282
|
+
this._state[propertyName] = children.sort((a, b) => a.idx - b.idx).map(_ => _.child);
|
|
273
283
|
});
|
|
274
|
-
|
|
284
|
+
|
|
285
|
+
// Compare the content of each slot with the cached values and invalidate for the ones that changed
|
|
286
|
+
let invalidated = false;
|
|
287
|
+
for (const [slotName, slotData] of Object.entries(slotsMap)) { // eslint-disable-line
|
|
288
|
+
const propertyName = slotData.propertyName || slotName;
|
|
289
|
+
if (!arraysAreEqual(slotsCachedContentMap.get(propertyName), this._state[propertyName])) {
|
|
290
|
+
_invalidate.call(this, {
|
|
291
|
+
type: "slot",
|
|
292
|
+
name: propertyNameToSlotMap.get(propertyName),
|
|
293
|
+
reason: "children",
|
|
294
|
+
});
|
|
295
|
+
invalidated = true;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// If none of the slots had an invalidation due to changes to immediate children,
|
|
300
|
+
// the change is considered to be text content of the default slot
|
|
301
|
+
if (!invalidated) {
|
|
302
|
+
_invalidate.call(this, {
|
|
303
|
+
type: "slot",
|
|
304
|
+
name: "default",
|
|
305
|
+
reason: "textcontent",
|
|
306
|
+
});
|
|
307
|
+
}
|
|
275
308
|
}
|
|
276
309
|
|
|
277
310
|
/**
|
|
@@ -280,24 +313,62 @@ class UI5Element extends HTMLElement {
|
|
|
280
313
|
*/
|
|
281
314
|
_clearSlot(slotName, slotData) {
|
|
282
315
|
const propertyName = slotData.propertyName || slotName;
|
|
283
|
-
|
|
284
|
-
let children = this._state[propertyName];
|
|
285
|
-
if (!Array.isArray(children)) {
|
|
286
|
-
children = [children];
|
|
287
|
-
}
|
|
316
|
+
const children = this._state[propertyName];
|
|
288
317
|
|
|
289
318
|
children.forEach(child => {
|
|
290
319
|
if (child && child.isUI5Element) {
|
|
291
|
-
|
|
320
|
+
const method = (child.detachInvalidate || child._detachChange).bind(child);
|
|
321
|
+
method(this._getChildChangeListener(slotName));
|
|
292
322
|
}
|
|
293
323
|
|
|
294
324
|
if (isSlot(child)) {
|
|
295
|
-
this._detachSlotChange(child);
|
|
325
|
+
this._detachSlotChange(child, slotName);
|
|
296
326
|
}
|
|
297
327
|
});
|
|
298
328
|
|
|
299
329
|
this._state[propertyName] = [];
|
|
300
|
-
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Attach a callback that will be executed whenever the component is invalidated
|
|
334
|
+
*
|
|
335
|
+
* @param callback
|
|
336
|
+
* @public
|
|
337
|
+
*/
|
|
338
|
+
attachInvalidate(callback) {
|
|
339
|
+
this._eventProvider.attachEvent("invalidate", callback);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Detach the callback that is executed whenever the component is invalidated
|
|
344
|
+
*
|
|
345
|
+
* @param callback
|
|
346
|
+
* @public
|
|
347
|
+
*/
|
|
348
|
+
detachInvalidate(callback) {
|
|
349
|
+
this._eventProvider.detachEvent("invalidate", callback);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Callback that is executed whenever a monitored child changes its state
|
|
354
|
+
*
|
|
355
|
+
* @param slotName the slot in which a child was invalidated
|
|
356
|
+
* @param childChangeInfo the changeInfo object for the child in the given slot
|
|
357
|
+
* @private
|
|
358
|
+
*/
|
|
359
|
+
_onChildChange(slotName, childChangeInfo) {
|
|
360
|
+
if (!this.constructor.getMetadata().shouldInvalidateOnChildChange(slotName, childChangeInfo.type, childChangeInfo.name)) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// The component should be invalidated as this type of change on the child is listened for
|
|
365
|
+
// However, no matter what changed on the child (property/slot), the invalidation is registered as "type=slot" for the component itself
|
|
366
|
+
_invalidate.call(this, {
|
|
367
|
+
type: "slot",
|
|
368
|
+
name: slotName,
|
|
369
|
+
reason: "childchange",
|
|
370
|
+
child: childChangeInfo.target,
|
|
371
|
+
});
|
|
301
372
|
}
|
|
302
373
|
|
|
303
374
|
/**
|
|
@@ -312,12 +383,8 @@ class UI5Element extends HTMLElement {
|
|
|
312
383
|
const propertyTypeClass = properties[nameInCamelCase].type;
|
|
313
384
|
if (propertyTypeClass === Boolean) {
|
|
314
385
|
newValue = newValue !== null;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
newValue = parseInt(newValue);
|
|
318
|
-
}
|
|
319
|
-
if (propertyTypeClass === Float) {
|
|
320
|
-
newValue = parseFloat(newValue);
|
|
386
|
+
} else if (isDescendantOf(propertyTypeClass, DataType)) {
|
|
387
|
+
newValue = propertyTypeClass.attributeToProperty(newValue);
|
|
321
388
|
}
|
|
322
389
|
this[nameInCamelCase] = newValue;
|
|
323
390
|
}
|
|
@@ -330,22 +397,24 @@ class UI5Element extends HTMLElement {
|
|
|
330
397
|
if (!this.constructor.getMetadata().hasAttribute(name)) {
|
|
331
398
|
return;
|
|
332
399
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
|
|
400
|
+
const properties = this.constructor.getMetadata().getProperties();
|
|
401
|
+
const propertyTypeClass = properties[name].type;
|
|
338
402
|
const attrName = camelToKebabCase(name);
|
|
339
403
|
const attrValue = this.getAttribute(attrName);
|
|
340
|
-
|
|
404
|
+
|
|
405
|
+
if (propertyTypeClass === Boolean) {
|
|
341
406
|
if (newValue === true && attrValue === null) {
|
|
342
407
|
this.setAttribute(attrName, "");
|
|
343
408
|
} else if (newValue === false && attrValue !== null) {
|
|
344
409
|
this.removeAttribute(attrName);
|
|
345
410
|
}
|
|
346
|
-
} else if (
|
|
347
|
-
this.setAttribute(attrName, newValue);
|
|
348
|
-
}
|
|
411
|
+
} else if (isDescendantOf(propertyTypeClass, DataType)) {
|
|
412
|
+
this.setAttribute(attrName, propertyTypeClass.propertyToAttribute(newValue));
|
|
413
|
+
} else if (typeof newValue !== "object") {
|
|
414
|
+
if (attrValue !== newValue) {
|
|
415
|
+
this.setAttribute(attrName, newValue);
|
|
416
|
+
}
|
|
417
|
+
} // else { return; } // old object handling
|
|
349
418
|
}
|
|
350
419
|
|
|
351
420
|
/**
|
|
@@ -371,120 +440,96 @@ class UI5Element extends HTMLElement {
|
|
|
371
440
|
* @private
|
|
372
441
|
*/
|
|
373
442
|
_initializeState() {
|
|
374
|
-
|
|
375
|
-
this._state = Object.assign({}, defaultState);
|
|
443
|
+
this._state = { ...this.constructor.getMetadata().getInitialState() };
|
|
376
444
|
}
|
|
377
445
|
|
|
378
446
|
/**
|
|
447
|
+
* Returns a singleton event listener for the "change" event of a child in a given slot
|
|
448
|
+
*
|
|
449
|
+
* @param slotName the name of the slot, where the child is
|
|
450
|
+
* @returns {any}
|
|
379
451
|
* @private
|
|
380
452
|
*/
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
slotName
|
|
384
|
-
childProperties = childMetadata.getProperties();
|
|
385
|
-
|
|
386
|
-
let observedProps = [],
|
|
387
|
-
notObservedProps = [];
|
|
388
|
-
|
|
389
|
-
if (Array.isArray(listenFor)) {
|
|
390
|
-
observedProps = listenFor;
|
|
391
|
-
} else {
|
|
392
|
-
observedProps = Array.isArray(listenFor.props) ? listenFor.props : Object.keys(childProperties);
|
|
393
|
-
notObservedProps = Array.isArray(listenFor.exclude) ? listenFor.exclude : [];
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
if (!this._monitoredChildProps.has(slotName)) {
|
|
397
|
-
this._monitoredChildProps.set(slotName, { observedProps, notObservedProps });
|
|
453
|
+
_getChildChangeListener(slotName) {
|
|
454
|
+
if (!this._childChangeListeners.has(slotName)) {
|
|
455
|
+
this._childChangeListeners.set(slotName, this._onChildChange.bind(this, slotName));
|
|
398
456
|
}
|
|
399
|
-
|
|
400
|
-
child.addEventListener("_property-change", this._invalidateParentOnPropertyUpdate);
|
|
401
|
-
child._firePropertyChange = true;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/**
|
|
405
|
-
* @private
|
|
406
|
-
*/
|
|
407
|
-
_detachChildPropertyUpdated(child) {
|
|
408
|
-
child.removeEventListener("_property-change", this._invalidateParentOnPropertyUpdate);
|
|
409
|
-
child._firePropertyChange = false;
|
|
457
|
+
return this._childChangeListeners.get(slotName);
|
|
410
458
|
}
|
|
411
459
|
|
|
412
460
|
/**
|
|
461
|
+
* Returns a singleton slotchange event listener that invalidates the component due to changes in the given slot
|
|
462
|
+
*
|
|
463
|
+
* @param slotName the name of the slot, where the slot element (whose slotchange event we're listening to) is
|
|
464
|
+
* @returns {any}
|
|
413
465
|
* @private
|
|
414
466
|
*/
|
|
415
|
-
|
|
416
|
-
this.
|
|
417
|
-
|
|
418
|
-
if (this._firePropertyChange) {
|
|
419
|
-
this.dispatchEvent(new CustomEvent("_property-change", {
|
|
420
|
-
detail: { name, newValue: value },
|
|
421
|
-
composed: false,
|
|
422
|
-
bubbles: true,
|
|
423
|
-
}));
|
|
467
|
+
_getSlotChangeListener(slotName) {
|
|
468
|
+
if (!this._slotChangeListeners.has(slotName)) {
|
|
469
|
+
this._slotChangeListeners.set(slotName, this._onSlotChange.bind(this, slotName));
|
|
424
470
|
}
|
|
471
|
+
return this._slotChangeListeners.get(slotName);
|
|
425
472
|
}
|
|
426
473
|
|
|
427
474
|
/**
|
|
428
475
|
* @private
|
|
429
476
|
*/
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
const parentNode = this.parentNode;
|
|
433
|
-
if (!parentNode) {
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
const slotName = parentNode.constructor._getSlotName(this);
|
|
438
|
-
const propsMetadata = parentNode._monitoredChildProps.get(slotName);
|
|
439
|
-
|
|
440
|
-
if (!propsMetadata) {
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
const { observedProps, notObservedProps } = propsMetadata;
|
|
444
|
-
|
|
445
|
-
if (observedProps.includes(prop.detail.name) && !notObservedProps.includes(prop.detail.name)) {
|
|
446
|
-
parentNode._invalidate("_parent_", this);
|
|
447
|
-
}
|
|
477
|
+
_attachSlotChange(child, slotName) {
|
|
478
|
+
child.addEventListener("slotchange", this._getSlotChangeListener(slotName));
|
|
448
479
|
}
|
|
449
480
|
|
|
450
481
|
/**
|
|
451
482
|
* @private
|
|
452
483
|
*/
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
this._invalidateOnSlotChange = () => {
|
|
456
|
-
this._invalidate("slotchange");
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
child.addEventListener("slotchange", this._invalidateOnSlotChange);
|
|
484
|
+
_detachSlotChange(child, slotName) {
|
|
485
|
+
child.removeEventListener("slotchange", this._getSlotChangeListener(slotName));
|
|
460
486
|
}
|
|
461
487
|
|
|
462
488
|
/**
|
|
489
|
+
* Whenever a slot element is slotted inside a UI5 Web Component, its slotchange event invalidates the component
|
|
490
|
+
*
|
|
491
|
+
* @param slotName the name of the slot, where the slot element (whose slotchange event we're listening to) is
|
|
463
492
|
* @private
|
|
464
493
|
*/
|
|
465
|
-
|
|
466
|
-
|
|
494
|
+
_onSlotChange(slotName) {
|
|
495
|
+
_invalidate.call(this, {
|
|
496
|
+
type: "slot",
|
|
497
|
+
name: slotName,
|
|
498
|
+
reason: "slotchange",
|
|
499
|
+
});
|
|
467
500
|
}
|
|
468
501
|
|
|
469
502
|
/**
|
|
470
|
-
*
|
|
471
|
-
*
|
|
503
|
+
* A callback that is executed each time an already rendered component is invalidated (scheduled for re-rendering)
|
|
504
|
+
*
|
|
505
|
+
* @param changeInfo An object with information about the change that caused invalidation.
|
|
506
|
+
* The object can have the following properties:
|
|
507
|
+
* - type: (property|slot) tells what caused the invalidation
|
|
508
|
+
* 1) property: a property value was changed either directly or as a result of changing the corresponding attribute
|
|
509
|
+
* 2) slot: a slotted node(nodes) changed in one of several ways (see "reason")
|
|
510
|
+
*
|
|
511
|
+
* - name: the name of the property or slot that caused the invalidation
|
|
512
|
+
*
|
|
513
|
+
* - reason: (children|textcontent|childchange|slotchange) relevant only for type="slot" only and tells exactly what changed in the slot
|
|
514
|
+
* 1) children: immediate children (HTML elements or text nodes) were added, removed or reordered in the slot
|
|
515
|
+
* 2) textcontent: text nodes in the slot changed value (or nested text nodes were added or changed value). Can only trigger for slots of "type: Node"
|
|
516
|
+
* 3) slotchange: a slot element, slotted inside that slot had its "slotchange" event listener called. This practically means that transitively slotted children changed.
|
|
517
|
+
* Can only trigger if the child of a slot is a slot element itself.
|
|
518
|
+
* 4) childchange: indicates that a UI5Element child in that slot was invalidated and in turn invalidated the component.
|
|
519
|
+
* Can only trigger for slots with "invalidateOnChildChange" metadata descriptor
|
|
520
|
+
*
|
|
521
|
+
* - newValue: the new value of the property (for type="property" only)
|
|
522
|
+
*
|
|
523
|
+
* - oldValue: the old value of the property (for type="property" only)
|
|
524
|
+
*
|
|
525
|
+
* - child the child that was changed (for type="slot" and reason="childchange" only)
|
|
526
|
+
*
|
|
527
|
+
* @public
|
|
472
528
|
*/
|
|
473
|
-
|
|
474
|
-
if (!this._upToDate) {
|
|
475
|
-
// console.log("already invalidated", this, ...arguments);
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
if (this.getDomRef() && !this._suppressInvalidation) {
|
|
480
|
-
this._upToDate = false;
|
|
481
|
-
// console.log("INVAL", this, ...arguments);
|
|
482
|
-
RenderScheduler.renderDeferred(this);
|
|
483
|
-
}
|
|
484
|
-
}
|
|
529
|
+
onInvalidation(changeInfo) {}
|
|
485
530
|
|
|
486
531
|
/**
|
|
487
|
-
* Do not call this method directly, only intended to be called by
|
|
532
|
+
* Do not call this method directly, only intended to be called by js
|
|
488
533
|
* @protected
|
|
489
534
|
*/
|
|
490
535
|
_render() {
|
|
@@ -503,15 +548,37 @@ class UI5Element extends HTMLElement {
|
|
|
503
548
|
}
|
|
504
549
|
|
|
505
550
|
// resume normal invalidation handling
|
|
506
|
-
|
|
551
|
+
this._suppressInvalidation = false;
|
|
507
552
|
|
|
508
553
|
// Update the shadow root with the render result
|
|
509
|
-
|
|
510
|
-
this.
|
|
511
|
-
|
|
554
|
+
/*
|
|
555
|
+
if (this._changedState.length) {
|
|
556
|
+
let element = this.localName;
|
|
557
|
+
if (this.id) {
|
|
558
|
+
element = `${element}#${this.id}`;
|
|
559
|
+
}
|
|
560
|
+
console.log("Re-rendering:", element, this._changedState.map(x => { // eslint-disable-line
|
|
561
|
+
let res = `${x.type}`;
|
|
562
|
+
if (x.reason) {
|
|
563
|
+
res = `${res}(${x.reason})`;
|
|
564
|
+
}
|
|
565
|
+
res = `${res}: ${x.name}`;
|
|
566
|
+
if (x.type === "property") {
|
|
567
|
+
res = `${res} ${x.oldValue} => ${x.newValue}`;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return res;
|
|
571
|
+
}));
|
|
572
|
+
}
|
|
573
|
+
*/
|
|
574
|
+
this._changedState = [];
|
|
512
575
|
|
|
513
|
-
|
|
514
|
-
|
|
576
|
+
// Update shadow root and static area item
|
|
577
|
+
if (this.constructor._needsShadowDOM()) {
|
|
578
|
+
updateShadowRoot(this);
|
|
579
|
+
}
|
|
580
|
+
if (this.staticAreaItem) {
|
|
581
|
+
this.staticAreaItem.update();
|
|
515
582
|
}
|
|
516
583
|
|
|
517
584
|
// Safari requires that children get the slot attribute only after the slot tags have been rendered in the shadow DOM
|
|
@@ -525,23 +592,6 @@ class UI5Element extends HTMLElement {
|
|
|
525
592
|
}
|
|
526
593
|
}
|
|
527
594
|
|
|
528
|
-
/**
|
|
529
|
-
* @private
|
|
530
|
-
*/
|
|
531
|
-
_updateShadowRoot() {
|
|
532
|
-
if (!this.constructor._needsShadowDOM()) {
|
|
533
|
-
return;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
let styleToPrepend;
|
|
537
|
-
const renderResult = this.constructor.template(this);
|
|
538
|
-
|
|
539
|
-
if (!document.adoptedStyleSheets && !window.ShadyDOM) {
|
|
540
|
-
styleToPrepend = getEffectiveStyle(this.constructor);
|
|
541
|
-
}
|
|
542
|
-
this.constructor.render(renderResult, this.shadowRoot, styleToPrepend, { eventContext: this });
|
|
543
|
-
}
|
|
544
|
-
|
|
545
595
|
/**
|
|
546
596
|
* @private
|
|
547
597
|
*/
|
|
@@ -564,16 +614,27 @@ class UI5Element extends HTMLElement {
|
|
|
564
614
|
|
|
565
615
|
/**
|
|
566
616
|
* Returns the DOM Element inside the Shadow Root that corresponds to the opening tag in the UI5 Web Component's template
|
|
617
|
+
* *Note:* For logical (abstract) elements (items, options, etc...), returns the part of the parent's DOM that represents this option
|
|
567
618
|
* Use this method instead of "this.shadowRoot" to read the Shadow DOM, if ever necessary
|
|
619
|
+
*
|
|
568
620
|
* @public
|
|
569
621
|
*/
|
|
570
622
|
getDomRef() {
|
|
623
|
+
// If a component set _getRealDomRef to its children, use the return value of this function
|
|
624
|
+
if (typeof this._getRealDomRef === "function") {
|
|
625
|
+
return this._getRealDomRef();
|
|
626
|
+
}
|
|
627
|
+
|
|
571
628
|
if (!this.shadowRoot || this.shadowRoot.children.length === 0) {
|
|
572
629
|
return;
|
|
573
630
|
}
|
|
574
631
|
|
|
575
|
-
|
|
576
|
-
|
|
632
|
+
const children = [...this.shadowRoot.children].filter(child => !["link", "style"].includes(child.localName));
|
|
633
|
+
if (children.length !== 1) {
|
|
634
|
+
console.warn(`The shadow DOM for ${this.constructor.getMetadata().getTag()} does not have a top level element, the getDomRef() method might not work as expected`); // eslint-disable-line
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
return children[0];
|
|
577
638
|
}
|
|
578
639
|
|
|
579
640
|
/**
|
|
@@ -589,6 +650,16 @@ class UI5Element extends HTMLElement {
|
|
|
589
650
|
}
|
|
590
651
|
}
|
|
591
652
|
|
|
653
|
+
/**
|
|
654
|
+
* Waits for dom ref and then returns the DOM Element marked with "data-sap-focus-ref" inside the template.
|
|
655
|
+
* This is the element that will receive the focus by default.
|
|
656
|
+
* @public
|
|
657
|
+
*/
|
|
658
|
+
async getFocusDomRefAsync() {
|
|
659
|
+
await this._waitForDomRef();
|
|
660
|
+
return this.getFocusDomRef();
|
|
661
|
+
}
|
|
662
|
+
|
|
592
663
|
/**
|
|
593
664
|
* Set the focus to the element, returned by "getFocusDomRef()" (marked by "data-sap-focus-ref")
|
|
594
665
|
* @public
|
|
@@ -609,10 +680,11 @@ class UI5Element extends HTMLElement {
|
|
|
609
680
|
* @param name - name of the event
|
|
610
681
|
* @param data - additional data for the event
|
|
611
682
|
* @param cancelable - true, if the user can call preventDefault on the event object
|
|
683
|
+
* @param bubbles - true, if the event bubbles
|
|
612
684
|
* @returns {boolean} false, if the event was cancelled (preventDefault called), true otherwise
|
|
613
685
|
*/
|
|
614
|
-
fireEvent(name, data, cancelable) {
|
|
615
|
-
const eventResult = this._fireEvent(name, data, cancelable);
|
|
686
|
+
fireEvent(name, data, cancelable = false, bubbles = true) {
|
|
687
|
+
const eventResult = this._fireEvent(name, data, cancelable, bubbles);
|
|
616
688
|
const camelCaseEventName = kebabToCamelCase(name);
|
|
617
689
|
|
|
618
690
|
if (camelCaseEventName !== name) {
|
|
@@ -622,35 +694,33 @@ class UI5Element extends HTMLElement {
|
|
|
622
694
|
return eventResult;
|
|
623
695
|
}
|
|
624
696
|
|
|
625
|
-
_fireEvent(name, data, cancelable) {
|
|
626
|
-
let compatEventResult = true; // Initialized to true, because if the event is not fired at all, it should be considered "not-prevented"
|
|
627
|
-
|
|
697
|
+
_fireEvent(name, data, cancelable = false, bubbles = true) {
|
|
628
698
|
const noConflictEvent = new CustomEvent(`ui5-${name}`, {
|
|
629
699
|
detail: data,
|
|
630
700
|
composed: false,
|
|
631
|
-
bubbles
|
|
701
|
+
bubbles,
|
|
632
702
|
cancelable,
|
|
633
703
|
});
|
|
634
704
|
|
|
635
|
-
// This will be false if the
|
|
636
|
-
|
|
705
|
+
// This will be false if the no-conflict event is prevented
|
|
706
|
+
const noConflictEventResult = this.dispatchEvent(noConflictEvent);
|
|
637
707
|
|
|
638
708
|
if (skipOriginalEvent(name)) {
|
|
639
|
-
return
|
|
709
|
+
return noConflictEventResult;
|
|
640
710
|
}
|
|
641
711
|
|
|
642
|
-
const
|
|
712
|
+
const normalEvent = new CustomEvent(name, {
|
|
643
713
|
detail: data,
|
|
644
714
|
composed: false,
|
|
645
|
-
bubbles
|
|
715
|
+
bubbles,
|
|
646
716
|
cancelable,
|
|
647
717
|
});
|
|
648
718
|
|
|
649
719
|
// This will be false if the normal event is prevented
|
|
650
|
-
const normalEventResult = this.dispatchEvent(
|
|
720
|
+
const normalEventResult = this.dispatchEvent(normalEvent);
|
|
651
721
|
|
|
652
722
|
// Return false if any of the two events was prevented (its result was false).
|
|
653
|
-
return normalEventResult &&
|
|
723
|
+
return normalEventResult && noConflictEventResult;
|
|
654
724
|
}
|
|
655
725
|
|
|
656
726
|
/**
|
|
@@ -659,18 +729,7 @@ class UI5Element extends HTMLElement {
|
|
|
659
729
|
* @public
|
|
660
730
|
*/
|
|
661
731
|
getSlottedNodes(slotName) {
|
|
662
|
-
|
|
663
|
-
if (!isSlot(curr)) {
|
|
664
|
-
return acc.concat([curr]);
|
|
665
|
-
}
|
|
666
|
-
return acc.concat(curr.assignedNodes({ flatten: true }).filter(item => item instanceof HTMLElement));
|
|
667
|
-
};
|
|
668
|
-
|
|
669
|
-
return this[slotName].reduce(reducer, []);
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
get isCompact() {
|
|
673
|
-
return getComputedStyle(this).getPropertyValue(GLOBAL_CONTENT_DENSITY_CSS_VAR) === "compact";
|
|
732
|
+
return getSlottedElementsList(this[slotName]);
|
|
674
733
|
}
|
|
675
734
|
|
|
676
735
|
/**
|
|
@@ -682,33 +741,7 @@ class UI5Element extends HTMLElement {
|
|
|
682
741
|
*/
|
|
683
742
|
get effectiveDir() {
|
|
684
743
|
markAsRtlAware(this.constructor); // if a UI5 Element calls this method, it's considered to be rtl-aware
|
|
685
|
-
|
|
686
|
-
const doc = window.document;
|
|
687
|
-
const dirValues = ["ltr", "rtl"]; // exclude "auto" and "" from all calculations
|
|
688
|
-
const locallyAppliedDir = getComputedStyle(this).getPropertyValue(GLOBAL_DIR_CSS_VAR);
|
|
689
|
-
|
|
690
|
-
// In that order, inspect the CSS Var (for modern browsers), the element itself, html and body (for IE fallback)
|
|
691
|
-
if (dirValues.includes(locallyAppliedDir)) {
|
|
692
|
-
return locallyAppliedDir;
|
|
693
|
-
}
|
|
694
|
-
if (dirValues.includes(this.dir)) {
|
|
695
|
-
return this.dir;
|
|
696
|
-
}
|
|
697
|
-
if (dirValues.includes(doc.documentElement.dir)) {
|
|
698
|
-
return doc.documentElement.dir;
|
|
699
|
-
}
|
|
700
|
-
if (dirValues.includes(doc.body.dir)) {
|
|
701
|
-
return doc.body.dir;
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// Finally, check the configuration for explicitly set RTL or language-implied RTL
|
|
705
|
-
return getRTL() ? "rtl" : undefined;
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
updateStaticAreaItemContentDensity() {
|
|
709
|
-
if (this.staticAreaItem) {
|
|
710
|
-
this.staticAreaItem._updateContentDensity(this.isCompact);
|
|
711
|
-
}
|
|
744
|
+
return getEffectiveDir(this);
|
|
712
745
|
}
|
|
713
746
|
|
|
714
747
|
/**
|
|
@@ -728,26 +761,6 @@ class UI5Element extends HTMLElement {
|
|
|
728
761
|
return this.getMetadata().getAttributesList();
|
|
729
762
|
}
|
|
730
763
|
|
|
731
|
-
/**
|
|
732
|
-
* @private
|
|
733
|
-
*/
|
|
734
|
-
static _getSlotName(child) {
|
|
735
|
-
// Text nodes can only go to the default slot
|
|
736
|
-
if (!(child instanceof HTMLElement)) {
|
|
737
|
-
return "default";
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
// Discover the slot based on the real slot name (f.e. footer => footer, or content-32 => content)
|
|
741
|
-
const slot = child.getAttribute("slot");
|
|
742
|
-
if (slot) {
|
|
743
|
-
const match = slot.match(/^(.+?)-\d+$/);
|
|
744
|
-
return match ? match[1] : slot;
|
|
745
|
-
}
|
|
746
|
-
|
|
747
|
-
// Use default slot as a fallback
|
|
748
|
-
return "default";
|
|
749
|
-
}
|
|
750
|
-
|
|
751
764
|
/**
|
|
752
765
|
* @private
|
|
753
766
|
*/
|
|
@@ -755,70 +768,30 @@ class UI5Element extends HTMLElement {
|
|
|
755
768
|
return !!this.template;
|
|
756
769
|
}
|
|
757
770
|
|
|
758
|
-
_shouldUpdateFragment() {
|
|
759
|
-
return this.constructor._needsStaticArea() && this.staticAreaItem.isRendered();
|
|
760
|
-
}
|
|
761
|
-
|
|
762
771
|
/**
|
|
763
772
|
* @private
|
|
764
773
|
*/
|
|
765
774
|
static _needsStaticArea() {
|
|
766
|
-
return
|
|
775
|
+
return !!this.staticAreaTemplate;
|
|
767
776
|
}
|
|
768
777
|
|
|
769
778
|
/**
|
|
770
779
|
* @public
|
|
771
780
|
*/
|
|
772
781
|
getStaticAreaItemDomRef() {
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
/**
|
|
777
|
-
* @private
|
|
778
|
-
*/
|
|
779
|
-
static _getDefaultState() {
|
|
780
|
-
if (this._defaultState) {
|
|
781
|
-
return this._defaultState;
|
|
782
|
+
if (!this.constructor._needsStaticArea()) {
|
|
783
|
+
throw new Error("This component does not use the static area");
|
|
782
784
|
}
|
|
783
785
|
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
// Initialize properties
|
|
789
|
-
const props = MetadataClass.getProperties();
|
|
790
|
-
for (const propName in props) { // eslint-disable-line
|
|
791
|
-
const propType = props[propName].type;
|
|
792
|
-
const propDefaultValue = props[propName].defaultValue;
|
|
793
|
-
|
|
794
|
-
if (propType === Boolean) {
|
|
795
|
-
defaultState[propName] = false;
|
|
796
|
-
|
|
797
|
-
if (propDefaultValue !== undefined) {
|
|
798
|
-
console.warn("The 'defaultValue' metadata key is ignored for all booleans properties, they would be initialized with 'false' by default"); // eslint-disable-line
|
|
799
|
-
}
|
|
800
|
-
} else if (props[propName].multiple) {
|
|
801
|
-
defaultState[propName] = [];
|
|
802
|
-
} else if (propType === Object) {
|
|
803
|
-
defaultState[propName] = "defaultValue" in props[propName] ? props[propName].defaultValue : {};
|
|
804
|
-
} else if (propType === String) {
|
|
805
|
-
defaultState[propName] = "defaultValue" in props[propName] ? props[propName].defaultValue : "";
|
|
806
|
-
} else {
|
|
807
|
-
defaultState[propName] = propDefaultValue;
|
|
808
|
-
}
|
|
786
|
+
if (!this.staticAreaItem) {
|
|
787
|
+
this.staticAreaItem = StaticAreaItem.createInstance();
|
|
788
|
+
this.staticAreaItem.setOwnerElement(this);
|
|
809
789
|
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
if (slotsAreManaged) {
|
|
813
|
-
const slots = MetadataClass.getSlots();
|
|
814
|
-
for (const [slotName, slotData] of Object.entries(slots)) { // eslint-disable-line
|
|
815
|
-
const propertyName = slotData.propertyName || slotName;
|
|
816
|
-
defaultState[propertyName] = [];
|
|
817
|
-
}
|
|
790
|
+
if (!this.staticAreaItem.parentElement) {
|
|
791
|
+
getSingletonElementInstance("ui5-static-area").appendChild(this.staticAreaItem);
|
|
818
792
|
}
|
|
819
793
|
|
|
820
|
-
this.
|
|
821
|
-
return defaultState;
|
|
794
|
+
return this.staticAreaItem.getDomRef();
|
|
822
795
|
}
|
|
823
796
|
|
|
824
797
|
/**
|
|
@@ -832,7 +805,7 @@ class UI5Element extends HTMLElement {
|
|
|
832
805
|
const properties = this.getMetadata().getProperties();
|
|
833
806
|
for (const [prop, propData] of Object.entries(properties)) { // eslint-disable-line
|
|
834
807
|
if (!isValidPropertyName(prop)) {
|
|
835
|
-
|
|
808
|
+
console.warn(`"${prop}" is not a valid property name. Use a name that does not collide with DOM APIs`); /* eslint-disable-line */
|
|
836
809
|
}
|
|
837
810
|
|
|
838
811
|
if (propData.type === Boolean && propData.defaultValue) {
|
|
@@ -870,14 +843,27 @@ class UI5Element extends HTMLElement {
|
|
|
870
843
|
}
|
|
871
844
|
},
|
|
872
845
|
set(value) {
|
|
846
|
+
let isDifferent;
|
|
873
847
|
value = this.constructor.getMetadata().constructor.validatePropertyValue(value, propData);
|
|
874
848
|
|
|
875
849
|
const oldState = this._state[prop];
|
|
850
|
+
if (propData.multiple && propData.compareValues) {
|
|
851
|
+
isDifferent = !arraysAreEqual(oldState, value);
|
|
852
|
+
} else if (isDescendantOf(propData.type, DataType)) {
|
|
853
|
+
isDifferent = !propData.type.valuesAreEqual(oldState, value);
|
|
854
|
+
} else {
|
|
855
|
+
isDifferent = oldState !== value;
|
|
856
|
+
}
|
|
876
857
|
|
|
877
|
-
if (
|
|
858
|
+
if (isDifferent) {
|
|
878
859
|
this._state[prop] = value;
|
|
879
|
-
|
|
880
|
-
|
|
860
|
+
_invalidate.call(this, {
|
|
861
|
+
type: "property",
|
|
862
|
+
name: prop,
|
|
863
|
+
newValue: value,
|
|
864
|
+
oldValue: oldState,
|
|
865
|
+
});
|
|
866
|
+
this._updateAttribute(prop, value);
|
|
881
867
|
}
|
|
882
868
|
},
|
|
883
869
|
});
|
|
@@ -888,7 +874,7 @@ class UI5Element extends HTMLElement {
|
|
|
888
874
|
const slots = this.getMetadata().getSlots();
|
|
889
875
|
for (const [slotName, slotData] of Object.entries(slots)) { // eslint-disable-line
|
|
890
876
|
if (!isValidPropertyName(slotName)) {
|
|
891
|
-
|
|
877
|
+
console.warn(`"${slotName}" is not a valid property name. Use a name that does not collide with DOM APIs`); /* eslint-disable-line */
|
|
892
878
|
}
|
|
893
879
|
|
|
894
880
|
const propertyName = slotData.propertyName || slotName;
|
|
@@ -900,7 +886,7 @@ class UI5Element extends HTMLElement {
|
|
|
900
886
|
return [];
|
|
901
887
|
},
|
|
902
888
|
set() {
|
|
903
|
-
throw new Error("Cannot set
|
|
889
|
+
throw new Error("Cannot set slot content directly, use the DOM APIs (appendChild, removeChild, etc...)");
|
|
904
890
|
},
|
|
905
891
|
});
|
|
906
892
|
}
|
|
@@ -915,6 +901,14 @@ class UI5Element extends HTMLElement {
|
|
|
915
901
|
return metadata;
|
|
916
902
|
}
|
|
917
903
|
|
|
904
|
+
/**
|
|
905
|
+
* Sets a new metadata object for this UI5 Web Component Class
|
|
906
|
+
* @protected
|
|
907
|
+
*/
|
|
908
|
+
static set metadata(newMetadata) {
|
|
909
|
+
metadata = newMetadata;
|
|
910
|
+
}
|
|
911
|
+
|
|
918
912
|
/**
|
|
919
913
|
* Returns the CSS for this UI5 Web Component Class
|
|
920
914
|
* @protected
|
|
@@ -931,6 +925,50 @@ class UI5Element extends HTMLElement {
|
|
|
931
925
|
return "";
|
|
932
926
|
}
|
|
933
927
|
|
|
928
|
+
/**
|
|
929
|
+
* Returns an array with the dependencies for this UI5 Web Component, which could be:
|
|
930
|
+
* - composed components (used in its shadow root or static area item)
|
|
931
|
+
* - slotted components that the component may need to communicate with
|
|
932
|
+
*
|
|
933
|
+
* @protected
|
|
934
|
+
*/
|
|
935
|
+
static get dependencies() {
|
|
936
|
+
return [];
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
/**
|
|
940
|
+
* Returns a list of the unique dependencies for this UI5 Web Component
|
|
941
|
+
*
|
|
942
|
+
* @public
|
|
943
|
+
*/
|
|
944
|
+
static getUniqueDependencies() {
|
|
945
|
+
if (!uniqueDependenciesCache.has(this)) {
|
|
946
|
+
const filtered = this.dependencies.filter((dep, index, deps) => deps.indexOf(dep) === index);
|
|
947
|
+
uniqueDependenciesCache.set(this, filtered);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
return uniqueDependenciesCache.get(this);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/**
|
|
954
|
+
* Returns a promise that resolves whenever all dependencies for this UI5 Web Component have resolved
|
|
955
|
+
*
|
|
956
|
+
* @returns {Promise<any[]>}
|
|
957
|
+
*/
|
|
958
|
+
static whenDependenciesDefined() {
|
|
959
|
+
return Promise.all(this.getUniqueDependencies().map(dep => dep.define()));
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
/**
|
|
963
|
+
* Hook that will be called upon custom element definition
|
|
964
|
+
*
|
|
965
|
+
* @protected
|
|
966
|
+
* @returns {Promise<void>}
|
|
967
|
+
*/
|
|
968
|
+
static async onDefine() {
|
|
969
|
+
return Promise.resolve();
|
|
970
|
+
}
|
|
971
|
+
|
|
934
972
|
/**
|
|
935
973
|
* Registers a UI5 Web Component in the browser window object
|
|
936
974
|
* @public
|
|
@@ -939,9 +977,10 @@ class UI5Element extends HTMLElement {
|
|
|
939
977
|
static async define() {
|
|
940
978
|
await boot();
|
|
941
979
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
980
|
+
await Promise.all([
|
|
981
|
+
this.whenDependenciesDefined(),
|
|
982
|
+
this.onDefine(),
|
|
983
|
+
]);
|
|
945
984
|
|
|
946
985
|
const tag = this.getMetadata().getTag();
|
|
947
986
|
const altTag = this.getMetadata().getAltTag();
|
|
@@ -955,11 +994,13 @@ class UI5Element extends HTMLElement {
|
|
|
955
994
|
this._generateAccessors();
|
|
956
995
|
registerTag(tag);
|
|
957
996
|
window.customElements.define(tag, this);
|
|
997
|
+
preloadLinks(this);
|
|
958
998
|
|
|
959
999
|
if (altTag && !customElements.get(altTag)) {
|
|
960
|
-
class oldClassName extends this {}
|
|
961
1000
|
registerTag(altTag);
|
|
962
|
-
window.customElements.define(altTag,
|
|
1001
|
+
window.customElements.define(altTag, getClassCopy(this, () => {
|
|
1002
|
+
console.log(`The ${altTag} tag is deprecated and will be removed in the next release, please use ${tag} instead.`); // eslint-disable-line
|
|
1003
|
+
}));
|
|
963
1004
|
}
|
|
964
1005
|
}
|
|
965
1006
|
return this;
|