@ui5/webcomponents-base 0.0.0-78035f8e7 → 0.0.0-8393c7cdd
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 +378 -0
- package/README.md +53 -7
- package/bundle.esm.js +20 -20
- 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 -29
- package/dist/StaticAreaItem.js +58 -62
- package/dist/SystemCSSVars.js +4 -25
- package/dist/Theming.js +2 -1
- package/dist/UI5Element.js +398 -354
- package/dist/UI5ElementMetadata.js +158 -18
- package/dist/asset-registries/Icons.js +118 -14
- 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 +64 -47
- package/dist/assets/bundle.esm.742a0a2e.js +43 -0
- 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 +66 -0
- package/dist/css/OverrideFontFace.css +32 -0
- package/dist/css/SystemCSSVars.css +17 -0
- package/dist/delegate/ItemNavigation.js +244 -170
- package/dist/delegate/ResizeHandler.js +78 -37
- package/dist/delegate/ScrollEnablement.js +49 -20
- package/dist/features/F6Navigation.js +110 -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/i18nBundle.js +39 -5
- 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 +43 -7
- package/dist/renderer/directives/style-map.js +72 -0
- package/dist/renderer/executeTemplate.js +34 -0
- 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/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/DOMReference.js +24 -0
- 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 +29 -0
- package/dist/util/AriaLabelHelper.js +39 -0
- package/dist/util/Caret.js +32 -0
- package/dist/util/ColorConversion.js +398 -0
- package/dist/util/FocusableElements.js +22 -9
- package/dist/util/HTMLSanitizer.js +7 -0
- package/dist/util/InvisibleMessage.js +69 -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/getEffectiveScrollbarStyle.js +5 -0
- package/dist/util/getNormalizedTarget.js +16 -0
- package/dist/util/isDefaultSlotProvided.js +11 -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 +37 -28
- package/package.json +20 -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 -29
- package/src/StaticAreaItem.js +58 -62
- package/src/SystemCSSVars.js +4 -25
- package/src/Theming.js +2 -1
- package/src/UI5Element.js +398 -354
- package/src/UI5ElementMetadata.js +158 -18
- package/src/asset-registries/Icons.js +118 -14
- 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 +64 -47
- 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 +66 -0
- package/src/css/OverrideFontFace.css +32 -0
- package/src/css/SystemCSSVars.css +17 -0
- package/src/delegate/ItemNavigation.js +244 -170
- package/src/delegate/ResizeHandler.js +78 -37
- package/src/delegate/ScrollEnablement.js +49 -20
- package/src/features/F6Navigation.js +110 -0
- package/src/features/OpenUI5Enablement.js +119 -0
- package/src/features/OpenUI5Support.js +42 -7
- package/src/i18nBundle.js +39 -5
- 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 +43 -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/DOMReference.js +24 -0
- 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 +29 -0
- package/src/util/AriaLabelHelper.js +39 -0
- package/src/util/Caret.js +32 -0
- package/src/util/ColorConversion.js +398 -0
- package/src/util/FocusableElements.js +22 -9
- package/src/util/HTMLSanitizer.js +7 -0
- package/src/util/InvisibleMessage.js +69 -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/getEffectiveScrollbarStyle.js +5 -0
- package/src/util/getNormalizedTarget.js +16 -0
- package/src/util/isDefaultSlotProvided.js +11 -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/config/.eslintrc.js +0 -3
- package/config/rollup.config.js +0 -1
- package/dist/SVGIconRegistry.js +0 -62
- 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/resources/bundle.esm.js +0 -129
- package/dist/resources/bundle.esm.js.map +0 -1
- package/dist/test-resources/assets/Themes.js +0 -13
- package/dist/test-resources/elements/Child.js +0 -35
- package/dist/test-resources/elements/Generic.js +0 -84
- package/dist/test-resources/elements/GenericExt.js +0 -26
- package/dist/test-resources/elements/NoShadowDOM.js +0 -13
- package/dist/test-resources/elements/Parent.js +0 -37
- package/dist/test-resources/elements/WithStaticArea.js +0 -76
- package/dist/test-resources/pages/AllTestElements.html +0 -42
- package/dist/test-resources/pages/Configuration.html +0 -20
- package/dist/test-resources/pages/ConfigurationScript.html +0 -36
- package/dist/test-resources/pages/assets/messagebundle_de.properties +0 -1
- package/dist/test-resources/pages/assets/messagebundle_en.properties +0 -1
- package/dist/test-resources/pages/assets/messagebundle_es.properties +0 -1
- package/dist/test-resources/pages/assets/messagebundle_fr.properties +0 -1
- package/dist/test-resources/pages/i18n.html +0 -40
- package/dist/test-resources/specs/ConfigurationChange.spec.js +0 -25
- package/dist/test-resources/specs/ConfigurationScript.spec.js +0 -61
- package/dist/test-resources/specs/ConfigurationURL.spec.js +0 -45
- package/dist/test-resources/specs/CustomTheme.spec.js +0 -25
- package/dist/test-resources/specs/StaticArea.spec.js +0 -34
- package/dist/test-resources/specs/Theming.spec.js +0 -31
- package/dist/test-resources/specs/UI5ElementInvalidation.js +0 -258
- package/dist/test-resources/specs/UI5ElementLifecycle.js +0 -93
- package/dist/test-resources/specs/UI5ElementListenForChildPropChanges.spec.js +0 -101
- package/dist/test-resources/specs/UI5ElementMetadataExt.js +0 -40
- package/dist/test-resources/specs/UI5ElementPropertyValidation.js +0 -12
- package/dist/test-resources/specs/UI5ElementPropsAndAttrs.spec.js +0 -65
- package/dist/test-resources/specs/UI5ElementShadowDOM.js +0 -22
- package/dist/test-resources/specs/UI5ElementSlots.js +0 -34
- 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/findNodeOwner.js +0 -35
- package/dist/util/getEffectiveAriaLabelText.js +0 -28
- 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 -62
- 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/findNodeOwner.js +0 -35
- package/src/util/getEffectiveAriaLabelText.js +0 -28
- 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,27 @@ 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;
|
|
77
|
+
this._doNotSyncAttributes = new Set(); // attributes that are excluded from attributeChangedCallback synchronization
|
|
56
78
|
|
|
57
|
-
this.
|
|
58
|
-
this.
|
|
79
|
+
this._initializeState();
|
|
80
|
+
this._upgradeAllProperties();
|
|
81
|
+
|
|
82
|
+
if (this.constructor._needsShadowDOM()) {
|
|
83
|
+
this.attachShadow({ mode: "open" });
|
|
84
|
+
}
|
|
59
85
|
}
|
|
60
86
|
|
|
61
87
|
/**
|
|
@@ -73,60 +99,34 @@ class UI5Element extends HTMLElement {
|
|
|
73
99
|
}
|
|
74
100
|
|
|
75
101
|
/**
|
|
102
|
+
* Do not call this method from derivatives of UI5Element, use "onEnterDOM" only
|
|
76
103
|
* @private
|
|
77
104
|
*/
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
105
|
+
async connectedCallback() {
|
|
106
|
+
this.setAttribute(this.constructor.getMetadata().getPureTag(), "");
|
|
107
|
+
if (this.constructor.getMetadata().supportsF6FastNavigation()) {
|
|
108
|
+
this.setAttribute("data-sap-ui-fastnavgroup", "true");
|
|
109
|
+
}
|
|
81
110
|
|
|
82
|
-
|
|
83
|
-
if (needsShadowDOM) {
|
|
84
|
-
this.attachShadow({ mode: "open" });
|
|
111
|
+
const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
|
|
85
112
|
|
|
86
|
-
|
|
87
|
-
if (window.ShadyDOM) {
|
|
88
|
-
createComponentStyleTag(this.constructor);
|
|
89
|
-
}
|
|
113
|
+
this._inDOM = true;
|
|
90
114
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
115
|
+
if (slotsAreManaged) {
|
|
116
|
+
// always register the observer before yielding control to the main thread (await)
|
|
117
|
+
this._startObservingDOMChildren();
|
|
118
|
+
await this._processChildren();
|
|
96
119
|
}
|
|
97
120
|
|
|
98
|
-
//
|
|
99
|
-
|
|
100
|
-
this.staticAreaItem = new StaticAreaItem(this);
|
|
121
|
+
if (!this._inDOM) { // Component removed from DOM while _processChildren was running
|
|
122
|
+
return;
|
|
101
123
|
}
|
|
102
|
-
}
|
|
103
124
|
|
|
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
|
-
}
|
|
125
|
+
renderImmediately(this);
|
|
126
|
+
this._domRefReadyPromise._deferredResolve();
|
|
127
|
+
this._fullyConnected = true;
|
|
128
|
+
if (typeof this.onEnterDOM === "function") {
|
|
129
|
+
this.onEnterDOM();
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
|
|
@@ -135,24 +135,26 @@ class UI5Element extends HTMLElement {
|
|
|
135
135
|
* @private
|
|
136
136
|
*/
|
|
137
137
|
disconnectedCallback() {
|
|
138
|
-
const needsShadowDOM = this.constructor._needsShadowDOM();
|
|
139
|
-
const needsStaticArea = this.constructor._needsStaticArea();
|
|
140
138
|
const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();
|
|
141
139
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
140
|
+
this._inDOM = false;
|
|
141
|
+
|
|
142
|
+
if (slotsAreManaged) {
|
|
143
|
+
this._stopObservingDOMChildren();
|
|
144
|
+
}
|
|
146
145
|
|
|
147
|
-
|
|
146
|
+
if (this._fullyConnected) {
|
|
148
147
|
if (typeof this.onExitDOM === "function") {
|
|
149
148
|
this.onExitDOM();
|
|
150
149
|
}
|
|
150
|
+
this._fullyConnected = false;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
if (
|
|
154
|
-
this.staticAreaItem.
|
|
153
|
+
if (this.staticAreaItem && this.staticAreaItem.parentElement) {
|
|
154
|
+
this.staticAreaItem.parentElement.removeChild(this.staticAreaItem);
|
|
155
155
|
}
|
|
156
|
+
|
|
157
|
+
cancelRender(this);
|
|
156
158
|
}
|
|
157
159
|
|
|
158
160
|
/**
|
|
@@ -168,16 +170,16 @@ class UI5Element extends HTMLElement {
|
|
|
168
170
|
const mutationObserverOptions = {
|
|
169
171
|
childList: true,
|
|
170
172
|
subtree: canSlotText,
|
|
171
|
-
characterData:
|
|
173
|
+
characterData: canSlotText,
|
|
172
174
|
};
|
|
173
|
-
|
|
175
|
+
observeDOMNode(this, this._processChildren.bind(this), mutationObserverOptions);
|
|
174
176
|
}
|
|
175
177
|
|
|
176
178
|
/**
|
|
177
179
|
* @private
|
|
178
180
|
*/
|
|
179
181
|
_stopObservingDOMChildren() {
|
|
180
|
-
|
|
182
|
+
unobserveDOMNode(this);
|
|
181
183
|
}
|
|
182
184
|
|
|
183
185
|
/**
|
|
@@ -199,8 +201,14 @@ class UI5Element extends HTMLElement {
|
|
|
199
201
|
const canSlotText = this.constructor.getMetadata().canSlotText();
|
|
200
202
|
const domChildren = Array.from(canSlotText ? this.childNodes : this.children);
|
|
201
203
|
|
|
202
|
-
//
|
|
204
|
+
const slotsCachedContentMap = new Map(); // Store here the content of each slot before the mutation occurred
|
|
205
|
+
const propertyNameToSlotMap = new Map(); // Used for reverse lookup to determine to which slot the property name corresponds
|
|
206
|
+
|
|
207
|
+
// Init the _state object based on the supported slots and store the previous values
|
|
203
208
|
for (const [slotName, slotData] of Object.entries(slotsMap)) { // eslint-disable-line
|
|
209
|
+
const propertyName = slotData.propertyName || slotName;
|
|
210
|
+
propertyNameToSlotMap.set(propertyName, slotName);
|
|
211
|
+
slotsCachedContentMap.set(propertyName, [...this._state[propertyName]]);
|
|
204
212
|
this._clearSlot(slotName, slotData);
|
|
205
213
|
}
|
|
206
214
|
|
|
@@ -209,7 +217,7 @@ class UI5Element extends HTMLElement {
|
|
|
209
217
|
|
|
210
218
|
const allChildrenUpgraded = domChildren.map(async (child, idx) => {
|
|
211
219
|
// Determine the type of the child (mainly by the slot attribute)
|
|
212
|
-
const slotName =
|
|
220
|
+
const slotName = getSlotName(child);
|
|
213
221
|
const slotData = slotsMap[slotName];
|
|
214
222
|
|
|
215
223
|
// Check if the slotName is supported
|
|
@@ -247,12 +255,15 @@ class UI5Element extends HTMLElement {
|
|
|
247
255
|
|
|
248
256
|
child = this.constructor.getMetadata().constructor.validateSlotValue(child, slotData);
|
|
249
257
|
|
|
250
|
-
if (
|
|
251
|
-
|
|
258
|
+
// Listen for any invalidation on the child if invalidateOnChildChange is true or an object (ignore when false or not set)
|
|
259
|
+
if (child.isUI5Element && slotData.invalidateOnChildChange) {
|
|
260
|
+
const method = (child.attachInvalidate || child._attachChange).bind(child);
|
|
261
|
+
method(this._getChildChangeListener(slotName));
|
|
252
262
|
}
|
|
253
263
|
|
|
264
|
+
// Listen for the slotchange event if the child is a slot itself
|
|
254
265
|
if (isSlot(child)) {
|
|
255
|
-
this._attachSlotChange(child);
|
|
266
|
+
this._attachSlotChange(child, slotName);
|
|
256
267
|
}
|
|
257
268
|
|
|
258
269
|
const propertyName = slotData.propertyName || slotName;
|
|
@@ -268,10 +279,33 @@ class UI5Element extends HTMLElement {
|
|
|
268
279
|
|
|
269
280
|
// Distribute the child in the _state object, keeping the Light DOM order,
|
|
270
281
|
// not the order elements are defined.
|
|
271
|
-
slottedChildrenMap.forEach((children,
|
|
272
|
-
this._state[
|
|
282
|
+
slottedChildrenMap.forEach((children, propertyName) => {
|
|
283
|
+
this._state[propertyName] = children.sort((a, b) => a.idx - b.idx).map(_ => _.child);
|
|
273
284
|
});
|
|
274
|
-
|
|
285
|
+
|
|
286
|
+
// Compare the content of each slot with the cached values and invalidate for the ones that changed
|
|
287
|
+
let invalidated = false;
|
|
288
|
+
for (const [slotName, slotData] of Object.entries(slotsMap)) { // eslint-disable-line
|
|
289
|
+
const propertyName = slotData.propertyName || slotName;
|
|
290
|
+
if (!arraysAreEqual(slotsCachedContentMap.get(propertyName), this._state[propertyName])) {
|
|
291
|
+
_invalidate.call(this, {
|
|
292
|
+
type: "slot",
|
|
293
|
+
name: propertyNameToSlotMap.get(propertyName),
|
|
294
|
+
reason: "children",
|
|
295
|
+
});
|
|
296
|
+
invalidated = true;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// If none of the slots had an invalidation due to changes to immediate children,
|
|
301
|
+
// the change is considered to be text content of the default slot
|
|
302
|
+
if (!invalidated) {
|
|
303
|
+
_invalidate.call(this, {
|
|
304
|
+
type: "slot",
|
|
305
|
+
name: "default",
|
|
306
|
+
reason: "textcontent",
|
|
307
|
+
});
|
|
308
|
+
}
|
|
275
309
|
}
|
|
276
310
|
|
|
277
311
|
/**
|
|
@@ -280,24 +314,62 @@ class UI5Element extends HTMLElement {
|
|
|
280
314
|
*/
|
|
281
315
|
_clearSlot(slotName, slotData) {
|
|
282
316
|
const propertyName = slotData.propertyName || slotName;
|
|
283
|
-
|
|
284
|
-
let children = this._state[propertyName];
|
|
285
|
-
if (!Array.isArray(children)) {
|
|
286
|
-
children = [children];
|
|
287
|
-
}
|
|
317
|
+
const children = this._state[propertyName];
|
|
288
318
|
|
|
289
319
|
children.forEach(child => {
|
|
290
320
|
if (child && child.isUI5Element) {
|
|
291
|
-
|
|
321
|
+
const method = (child.detachInvalidate || child._detachChange).bind(child);
|
|
322
|
+
method(this._getChildChangeListener(slotName));
|
|
292
323
|
}
|
|
293
324
|
|
|
294
325
|
if (isSlot(child)) {
|
|
295
|
-
this._detachSlotChange(child);
|
|
326
|
+
this._detachSlotChange(child, slotName);
|
|
296
327
|
}
|
|
297
328
|
});
|
|
298
329
|
|
|
299
330
|
this._state[propertyName] = [];
|
|
300
|
-
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Attach a callback that will be executed whenever the component is invalidated
|
|
335
|
+
*
|
|
336
|
+
* @param callback
|
|
337
|
+
* @public
|
|
338
|
+
*/
|
|
339
|
+
attachInvalidate(callback) {
|
|
340
|
+
this._eventProvider.attachEvent("invalidate", callback);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Detach the callback that is executed whenever the component is invalidated
|
|
345
|
+
*
|
|
346
|
+
* @param callback
|
|
347
|
+
* @public
|
|
348
|
+
*/
|
|
349
|
+
detachInvalidate(callback) {
|
|
350
|
+
this._eventProvider.detachEvent("invalidate", callback);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Callback that is executed whenever a monitored child changes its state
|
|
355
|
+
*
|
|
356
|
+
* @param slotName the slot in which a child was invalidated
|
|
357
|
+
* @param childChangeInfo the changeInfo object for the child in the given slot
|
|
358
|
+
* @private
|
|
359
|
+
*/
|
|
360
|
+
_onChildChange(slotName, childChangeInfo) {
|
|
361
|
+
if (!this.constructor.getMetadata().shouldInvalidateOnChildChange(slotName, childChangeInfo.type, childChangeInfo.name)) {
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// The component should be invalidated as this type of change on the child is listened for
|
|
366
|
+
// However, no matter what changed on the child (property/slot), the invalidation is registered as "type=slot" for the component itself
|
|
367
|
+
_invalidate.call(this, {
|
|
368
|
+
type: "slot",
|
|
369
|
+
name: slotName,
|
|
370
|
+
reason: "childchange",
|
|
371
|
+
child: childChangeInfo.target,
|
|
372
|
+
});
|
|
301
373
|
}
|
|
302
374
|
|
|
303
375
|
/**
|
|
@@ -305,6 +377,10 @@ class UI5Element extends HTMLElement {
|
|
|
305
377
|
* @private
|
|
306
378
|
*/
|
|
307
379
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
380
|
+
if (this._doNotSyncAttributes.has(name)) { // This attribute is mutated internally, not by the user
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
308
384
|
const properties = this.constructor.getMetadata().getProperties();
|
|
309
385
|
const realName = name.replace(/^ui5-/, "");
|
|
310
386
|
const nameInCamelCase = kebabToCamelCase(realName);
|
|
@@ -312,12 +388,8 @@ class UI5Element extends HTMLElement {
|
|
|
312
388
|
const propertyTypeClass = properties[nameInCamelCase].type;
|
|
313
389
|
if (propertyTypeClass === Boolean) {
|
|
314
390
|
newValue = newValue !== null;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
newValue = parseInt(newValue);
|
|
318
|
-
}
|
|
319
|
-
if (propertyTypeClass === Float) {
|
|
320
|
-
newValue = parseFloat(newValue);
|
|
391
|
+
} else if (isDescendantOf(propertyTypeClass, DataType)) {
|
|
392
|
+
newValue = propertyTypeClass.attributeToProperty(newValue);
|
|
321
393
|
}
|
|
322
394
|
this[nameInCamelCase] = newValue;
|
|
323
395
|
}
|
|
@@ -330,22 +402,31 @@ class UI5Element extends HTMLElement {
|
|
|
330
402
|
if (!this.constructor.getMetadata().hasAttribute(name)) {
|
|
331
403
|
return;
|
|
332
404
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
return;
|
|
336
|
-
}
|
|
337
|
-
|
|
405
|
+
const properties = this.constructor.getMetadata().getProperties();
|
|
406
|
+
const propertyTypeClass = properties[name].type;
|
|
338
407
|
const attrName = camelToKebabCase(name);
|
|
339
408
|
const attrValue = this.getAttribute(attrName);
|
|
340
|
-
|
|
409
|
+
|
|
410
|
+
if (propertyTypeClass === Boolean) {
|
|
341
411
|
if (newValue === true && attrValue === null) {
|
|
342
412
|
this.setAttribute(attrName, "");
|
|
343
413
|
} else if (newValue === false && attrValue !== null) {
|
|
344
414
|
this.removeAttribute(attrName);
|
|
345
415
|
}
|
|
346
|
-
} else if (
|
|
347
|
-
|
|
348
|
-
|
|
416
|
+
} else if (isDescendantOf(propertyTypeClass, DataType)) {
|
|
417
|
+
const newAttrValue = propertyTypeClass.propertyToAttribute(newValue);
|
|
418
|
+
if (newAttrValue === null) { // null means there must be no attribute for the current value of the property
|
|
419
|
+
this._doNotSyncAttributes.add(attrName); // skip the attributeChangedCallback call for this attribute
|
|
420
|
+
this.removeAttribute(attrName); // remove the attribute safely (will not trigger synchronization to the property value due to the above line)
|
|
421
|
+
this._doNotSyncAttributes.delete(attrName); // enable synchronization again for this attribute
|
|
422
|
+
} else {
|
|
423
|
+
this.setAttribute(attrName, newAttrValue);
|
|
424
|
+
}
|
|
425
|
+
} else if (typeof newValue !== "object") {
|
|
426
|
+
if (attrValue !== newValue) {
|
|
427
|
+
this.setAttribute(attrName, newValue);
|
|
428
|
+
}
|
|
429
|
+
} // else { return; } // old object handling
|
|
349
430
|
}
|
|
350
431
|
|
|
351
432
|
/**
|
|
@@ -371,120 +452,96 @@ class UI5Element extends HTMLElement {
|
|
|
371
452
|
* @private
|
|
372
453
|
*/
|
|
373
454
|
_initializeState() {
|
|
374
|
-
|
|
375
|
-
this._state = Object.assign({}, defaultState);
|
|
455
|
+
this._state = { ...this.constructor.getMetadata().getInitialState() };
|
|
376
456
|
}
|
|
377
457
|
|
|
378
458
|
/**
|
|
459
|
+
* Returns a singleton event listener for the "change" event of a child in a given slot
|
|
460
|
+
*
|
|
461
|
+
* @param slotName the name of the slot, where the child is
|
|
462
|
+
* @returns {any}
|
|
379
463
|
* @private
|
|
380
464
|
*/
|
|
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 : [];
|
|
465
|
+
_getChildChangeListener(slotName) {
|
|
466
|
+
if (!this._childChangeListeners.has(slotName)) {
|
|
467
|
+
this._childChangeListeners.set(slotName, this._onChildChange.bind(this, slotName));
|
|
394
468
|
}
|
|
395
|
-
|
|
396
|
-
if (!this._monitoredChildProps.has(slotName)) {
|
|
397
|
-
this._monitoredChildProps.set(slotName, { observedProps, notObservedProps });
|
|
398
|
-
}
|
|
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;
|
|
469
|
+
return this._childChangeListeners.get(slotName);
|
|
410
470
|
}
|
|
411
471
|
|
|
412
472
|
/**
|
|
473
|
+
* Returns a singleton slotchange event listener that invalidates the component due to changes in the given slot
|
|
474
|
+
*
|
|
475
|
+
* @param slotName the name of the slot, where the slot element (whose slotchange event we're listening to) is
|
|
476
|
+
* @returns {any}
|
|
413
477
|
* @private
|
|
414
478
|
*/
|
|
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
|
-
}));
|
|
479
|
+
_getSlotChangeListener(slotName) {
|
|
480
|
+
if (!this._slotChangeListeners.has(slotName)) {
|
|
481
|
+
this._slotChangeListeners.set(slotName, this._onSlotChange.bind(this, slotName));
|
|
424
482
|
}
|
|
483
|
+
return this._slotChangeListeners.get(slotName);
|
|
425
484
|
}
|
|
426
485
|
|
|
427
486
|
/**
|
|
428
487
|
* @private
|
|
429
488
|
*/
|
|
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
|
-
}
|
|
489
|
+
_attachSlotChange(child, slotName) {
|
|
490
|
+
child.addEventListener("slotchange", this._getSlotChangeListener(slotName));
|
|
448
491
|
}
|
|
449
492
|
|
|
450
493
|
/**
|
|
451
494
|
* @private
|
|
452
495
|
*/
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
this._invalidateOnSlotChange = () => {
|
|
456
|
-
this._invalidate("slotchange");
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
child.addEventListener("slotchange", this._invalidateOnSlotChange);
|
|
496
|
+
_detachSlotChange(child, slotName) {
|
|
497
|
+
child.removeEventListener("slotchange", this._getSlotChangeListener(slotName));
|
|
460
498
|
}
|
|
461
499
|
|
|
462
500
|
/**
|
|
501
|
+
* Whenever a slot element is slotted inside a UI5 Web Component, its slotchange event invalidates the component
|
|
502
|
+
*
|
|
503
|
+
* @param slotName the name of the slot, where the slot element (whose slotchange event we're listening to) is
|
|
463
504
|
* @private
|
|
464
505
|
*/
|
|
465
|
-
|
|
466
|
-
|
|
506
|
+
_onSlotChange(slotName) {
|
|
507
|
+
_invalidate.call(this, {
|
|
508
|
+
type: "slot",
|
|
509
|
+
name: slotName,
|
|
510
|
+
reason: "slotchange",
|
|
511
|
+
});
|
|
467
512
|
}
|
|
468
513
|
|
|
469
514
|
/**
|
|
470
|
-
*
|
|
471
|
-
*
|
|
515
|
+
* A callback that is executed each time an already rendered component is invalidated (scheduled for re-rendering)
|
|
516
|
+
*
|
|
517
|
+
* @param changeInfo An object with information about the change that caused invalidation.
|
|
518
|
+
* The object can have the following properties:
|
|
519
|
+
* - type: (property|slot) tells what caused the invalidation
|
|
520
|
+
* 1) property: a property value was changed either directly or as a result of changing the corresponding attribute
|
|
521
|
+
* 2) slot: a slotted node(nodes) changed in one of several ways (see "reason")
|
|
522
|
+
*
|
|
523
|
+
* - name: the name of the property or slot that caused the invalidation
|
|
524
|
+
*
|
|
525
|
+
* - reason: (children|textcontent|childchange|slotchange) relevant only for type="slot" only and tells exactly what changed in the slot
|
|
526
|
+
* 1) children: immediate children (HTML elements or text nodes) were added, removed or reordered in the slot
|
|
527
|
+
* 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"
|
|
528
|
+
* 3) slotchange: a slot element, slotted inside that slot had its "slotchange" event listener called. This practically means that transitively slotted children changed.
|
|
529
|
+
* Can only trigger if the child of a slot is a slot element itself.
|
|
530
|
+
* 4) childchange: indicates that a UI5Element child in that slot was invalidated and in turn invalidated the component.
|
|
531
|
+
* Can only trigger for slots with "invalidateOnChildChange" metadata descriptor
|
|
532
|
+
*
|
|
533
|
+
* - newValue: the new value of the property (for type="property" only)
|
|
534
|
+
*
|
|
535
|
+
* - oldValue: the old value of the property (for type="property" only)
|
|
536
|
+
*
|
|
537
|
+
* - child the child that was changed (for type="slot" and reason="childchange" only)
|
|
538
|
+
*
|
|
539
|
+
* @public
|
|
472
540
|
*/
|
|
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
|
-
}
|
|
541
|
+
onInvalidation(changeInfo) {}
|
|
485
542
|
|
|
486
543
|
/**
|
|
487
|
-
* Do not call this method directly, only intended to be called by
|
|
544
|
+
* Do not call this method directly, only intended to be called by js
|
|
488
545
|
* @protected
|
|
489
546
|
*/
|
|
490
547
|
_render() {
|
|
@@ -503,15 +560,37 @@ class UI5Element extends HTMLElement {
|
|
|
503
560
|
}
|
|
504
561
|
|
|
505
562
|
// resume normal invalidation handling
|
|
506
|
-
|
|
563
|
+
this._suppressInvalidation = false;
|
|
507
564
|
|
|
508
565
|
// Update the shadow root with the render result
|
|
509
|
-
|
|
510
|
-
this.
|
|
511
|
-
|
|
566
|
+
/*
|
|
567
|
+
if (this._changedState.length) {
|
|
568
|
+
let element = this.localName;
|
|
569
|
+
if (this.id) {
|
|
570
|
+
element = `${element}#${this.id}`;
|
|
571
|
+
}
|
|
572
|
+
console.log("Re-rendering:", element, this._changedState.map(x => { // eslint-disable-line
|
|
573
|
+
let res = `${x.type}`;
|
|
574
|
+
if (x.reason) {
|
|
575
|
+
res = `${res}(${x.reason})`;
|
|
576
|
+
}
|
|
577
|
+
res = `${res}: ${x.name}`;
|
|
578
|
+
if (x.type === "property") {
|
|
579
|
+
res = `${res} ${x.oldValue} => ${x.newValue}`;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
return res;
|
|
583
|
+
}));
|
|
584
|
+
}
|
|
585
|
+
*/
|
|
586
|
+
this._changedState = [];
|
|
512
587
|
|
|
513
|
-
|
|
514
|
-
|
|
588
|
+
// Update shadow root and static area item
|
|
589
|
+
if (this.constructor._needsShadowDOM()) {
|
|
590
|
+
updateShadowRoot(this);
|
|
591
|
+
}
|
|
592
|
+
if (this.staticAreaItem) {
|
|
593
|
+
this.staticAreaItem.update();
|
|
515
594
|
}
|
|
516
595
|
|
|
517
596
|
// Safari requires that children get the slot attribute only after the slot tags have been rendered in the shadow DOM
|
|
@@ -525,23 +604,6 @@ class UI5Element extends HTMLElement {
|
|
|
525
604
|
}
|
|
526
605
|
}
|
|
527
606
|
|
|
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
607
|
/**
|
|
546
608
|
* @private
|
|
547
609
|
*/
|
|
@@ -564,16 +626,27 @@ class UI5Element extends HTMLElement {
|
|
|
564
626
|
|
|
565
627
|
/**
|
|
566
628
|
* Returns the DOM Element inside the Shadow Root that corresponds to the opening tag in the UI5 Web Component's template
|
|
629
|
+
* *Note:* For logical (abstract) elements (items, options, etc...), returns the part of the parent's DOM that represents this option
|
|
567
630
|
* Use this method instead of "this.shadowRoot" to read the Shadow DOM, if ever necessary
|
|
631
|
+
*
|
|
568
632
|
* @public
|
|
569
633
|
*/
|
|
570
634
|
getDomRef() {
|
|
635
|
+
// If a component set _getRealDomRef to its children, use the return value of this function
|
|
636
|
+
if (typeof this._getRealDomRef === "function") {
|
|
637
|
+
return this._getRealDomRef();
|
|
638
|
+
}
|
|
639
|
+
|
|
571
640
|
if (!this.shadowRoot || this.shadowRoot.children.length === 0) {
|
|
572
641
|
return;
|
|
573
642
|
}
|
|
574
643
|
|
|
575
|
-
|
|
576
|
-
|
|
644
|
+
const children = [...this.shadowRoot.children].filter(child => !["link", "style"].includes(child.localName));
|
|
645
|
+
if (children.length !== 1) {
|
|
646
|
+
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
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
return children[0];
|
|
577
650
|
}
|
|
578
651
|
|
|
579
652
|
/**
|
|
@@ -590,12 +663,13 @@ class UI5Element extends HTMLElement {
|
|
|
590
663
|
}
|
|
591
664
|
|
|
592
665
|
/**
|
|
593
|
-
*
|
|
666
|
+
* Waits for dom ref and then returns the DOM Element marked with "data-sap-focus-ref" inside the template.
|
|
667
|
+
* This is the element that will receive the focus by default.
|
|
594
668
|
* @public
|
|
595
|
-
* @param {String} refName Defines the name of the stable DOM ref
|
|
596
669
|
*/
|
|
597
|
-
|
|
598
|
-
|
|
670
|
+
async getFocusDomRefAsync() {
|
|
671
|
+
await this._waitForDomRef();
|
|
672
|
+
return this.getFocusDomRef();
|
|
599
673
|
}
|
|
600
674
|
|
|
601
675
|
/**
|
|
@@ -618,10 +692,11 @@ class UI5Element extends HTMLElement {
|
|
|
618
692
|
* @param name - name of the event
|
|
619
693
|
* @param data - additional data for the event
|
|
620
694
|
* @param cancelable - true, if the user can call preventDefault on the event object
|
|
695
|
+
* @param bubbles - true, if the event bubbles
|
|
621
696
|
* @returns {boolean} false, if the event was cancelled (preventDefault called), true otherwise
|
|
622
697
|
*/
|
|
623
|
-
fireEvent(name, data, cancelable) {
|
|
624
|
-
const eventResult = this._fireEvent(name, data, cancelable);
|
|
698
|
+
fireEvent(name, data, cancelable = false, bubbles = true) {
|
|
699
|
+
const eventResult = this._fireEvent(name, data, cancelable, bubbles);
|
|
625
700
|
const camelCaseEventName = kebabToCamelCase(name);
|
|
626
701
|
|
|
627
702
|
if (camelCaseEventName !== name) {
|
|
@@ -631,35 +706,33 @@ class UI5Element extends HTMLElement {
|
|
|
631
706
|
return eventResult;
|
|
632
707
|
}
|
|
633
708
|
|
|
634
|
-
_fireEvent(name, data, cancelable) {
|
|
635
|
-
let compatEventResult = true; // Initialized to true, because if the event is not fired at all, it should be considered "not-prevented"
|
|
636
|
-
|
|
709
|
+
_fireEvent(name, data, cancelable = false, bubbles = true) {
|
|
637
710
|
const noConflictEvent = new CustomEvent(`ui5-${name}`, {
|
|
638
711
|
detail: data,
|
|
639
712
|
composed: false,
|
|
640
|
-
bubbles
|
|
713
|
+
bubbles,
|
|
641
714
|
cancelable,
|
|
642
715
|
});
|
|
643
716
|
|
|
644
|
-
// This will be false if the
|
|
645
|
-
|
|
717
|
+
// This will be false if the no-conflict event is prevented
|
|
718
|
+
const noConflictEventResult = this.dispatchEvent(noConflictEvent);
|
|
646
719
|
|
|
647
720
|
if (skipOriginalEvent(name)) {
|
|
648
|
-
return
|
|
721
|
+
return noConflictEventResult;
|
|
649
722
|
}
|
|
650
723
|
|
|
651
|
-
const
|
|
724
|
+
const normalEvent = new CustomEvent(name, {
|
|
652
725
|
detail: data,
|
|
653
726
|
composed: false,
|
|
654
|
-
bubbles
|
|
727
|
+
bubbles,
|
|
655
728
|
cancelable,
|
|
656
729
|
});
|
|
657
730
|
|
|
658
731
|
// This will be false if the normal event is prevented
|
|
659
|
-
const normalEventResult = this.dispatchEvent(
|
|
732
|
+
const normalEventResult = this.dispatchEvent(normalEvent);
|
|
660
733
|
|
|
661
734
|
// Return false if any of the two events was prevented (its result was false).
|
|
662
|
-
return normalEventResult &&
|
|
735
|
+
return normalEventResult && noConflictEventResult;
|
|
663
736
|
}
|
|
664
737
|
|
|
665
738
|
/**
|
|
@@ -668,18 +741,7 @@ class UI5Element extends HTMLElement {
|
|
|
668
741
|
* @public
|
|
669
742
|
*/
|
|
670
743
|
getSlottedNodes(slotName) {
|
|
671
|
-
|
|
672
|
-
if (!isSlot(curr)) {
|
|
673
|
-
return acc.concat([curr]);
|
|
674
|
-
}
|
|
675
|
-
return acc.concat(curr.assignedNodes({ flatten: true }).filter(item => item instanceof HTMLElement));
|
|
676
|
-
};
|
|
677
|
-
|
|
678
|
-
return this[slotName].reduce(reducer, []);
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
get isCompact() {
|
|
682
|
-
return getComputedStyle(this).getPropertyValue(GLOBAL_CONTENT_DENSITY_CSS_VAR) === "compact";
|
|
744
|
+
return getSlottedElementsList(this[slotName]);
|
|
683
745
|
}
|
|
684
746
|
|
|
685
747
|
/**
|
|
@@ -691,33 +753,7 @@ class UI5Element extends HTMLElement {
|
|
|
691
753
|
*/
|
|
692
754
|
get effectiveDir() {
|
|
693
755
|
markAsRtlAware(this.constructor); // if a UI5 Element calls this method, it's considered to be rtl-aware
|
|
694
|
-
|
|
695
|
-
const doc = window.document;
|
|
696
|
-
const dirValues = ["ltr", "rtl"]; // exclude "auto" and "" from all calculations
|
|
697
|
-
const locallyAppliedDir = getComputedStyle(this).getPropertyValue(GLOBAL_DIR_CSS_VAR);
|
|
698
|
-
|
|
699
|
-
// In that order, inspect the CSS Var (for modern browsers), the element itself, html and body (for IE fallback)
|
|
700
|
-
if (dirValues.includes(locallyAppliedDir)) {
|
|
701
|
-
return locallyAppliedDir;
|
|
702
|
-
}
|
|
703
|
-
if (dirValues.includes(this.dir)) {
|
|
704
|
-
return this.dir;
|
|
705
|
-
}
|
|
706
|
-
if (dirValues.includes(doc.documentElement.dir)) {
|
|
707
|
-
return doc.documentElement.dir;
|
|
708
|
-
}
|
|
709
|
-
if (dirValues.includes(doc.body.dir)) {
|
|
710
|
-
return doc.body.dir;
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
// Finally, check the configuration for explicitly set RTL or language-implied RTL
|
|
714
|
-
return getRTL() ? "rtl" : undefined;
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
updateStaticAreaItemContentDensity() {
|
|
718
|
-
if (this.staticAreaItem) {
|
|
719
|
-
this.staticAreaItem._updateContentDensity(this.isCompact);
|
|
720
|
-
}
|
|
756
|
+
return getEffectiveDir(this);
|
|
721
757
|
}
|
|
722
758
|
|
|
723
759
|
/**
|
|
@@ -737,26 +773,6 @@ class UI5Element extends HTMLElement {
|
|
|
737
773
|
return this.getMetadata().getAttributesList();
|
|
738
774
|
}
|
|
739
775
|
|
|
740
|
-
/**
|
|
741
|
-
* @private
|
|
742
|
-
*/
|
|
743
|
-
static _getSlotName(child) {
|
|
744
|
-
// Text nodes can only go to the default slot
|
|
745
|
-
if (!(child instanceof HTMLElement)) {
|
|
746
|
-
return "default";
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
// Discover the slot based on the real slot name (f.e. footer => footer, or content-32 => content)
|
|
750
|
-
const slot = child.getAttribute("slot");
|
|
751
|
-
if (slot) {
|
|
752
|
-
const match = slot.match(/^(.+?)-\d+$/);
|
|
753
|
-
return match ? match[1] : slot;
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
// Use default slot as a fallback
|
|
757
|
-
return "default";
|
|
758
|
-
}
|
|
759
|
-
|
|
760
776
|
/**
|
|
761
777
|
* @private
|
|
762
778
|
*/
|
|
@@ -764,70 +780,30 @@ class UI5Element extends HTMLElement {
|
|
|
764
780
|
return !!this.template;
|
|
765
781
|
}
|
|
766
782
|
|
|
767
|
-
_shouldUpdateFragment() {
|
|
768
|
-
return this.constructor._needsStaticArea() && this.staticAreaItem.isRendered();
|
|
769
|
-
}
|
|
770
|
-
|
|
771
783
|
/**
|
|
772
784
|
* @private
|
|
773
785
|
*/
|
|
774
786
|
static _needsStaticArea() {
|
|
775
|
-
return
|
|
787
|
+
return !!this.staticAreaTemplate;
|
|
776
788
|
}
|
|
777
789
|
|
|
778
790
|
/**
|
|
779
791
|
* @public
|
|
780
792
|
*/
|
|
781
793
|
getStaticAreaItemDomRef() {
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
/**
|
|
786
|
-
* @private
|
|
787
|
-
*/
|
|
788
|
-
static _getDefaultState() {
|
|
789
|
-
if (this._defaultState) {
|
|
790
|
-
return this._defaultState;
|
|
794
|
+
if (!this.constructor._needsStaticArea()) {
|
|
795
|
+
throw new Error("This component does not use the static area");
|
|
791
796
|
}
|
|
792
797
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
// Initialize properties
|
|
798
|
-
const props = MetadataClass.getProperties();
|
|
799
|
-
for (const propName in props) { // eslint-disable-line
|
|
800
|
-
const propType = props[propName].type;
|
|
801
|
-
const propDefaultValue = props[propName].defaultValue;
|
|
802
|
-
|
|
803
|
-
if (propType === Boolean) {
|
|
804
|
-
defaultState[propName] = false;
|
|
805
|
-
|
|
806
|
-
if (propDefaultValue !== undefined) {
|
|
807
|
-
console.warn("The 'defaultValue' metadata key is ignored for all booleans properties, they would be initialized with 'false' by default"); // eslint-disable-line
|
|
808
|
-
}
|
|
809
|
-
} else if (props[propName].multiple) {
|
|
810
|
-
defaultState[propName] = [];
|
|
811
|
-
} else if (propType === Object) {
|
|
812
|
-
defaultState[propName] = "defaultValue" in props[propName] ? props[propName].defaultValue : {};
|
|
813
|
-
} else if (propType === String) {
|
|
814
|
-
defaultState[propName] = "defaultValue" in props[propName] ? props[propName].defaultValue : "";
|
|
815
|
-
} else {
|
|
816
|
-
defaultState[propName] = propDefaultValue;
|
|
817
|
-
}
|
|
798
|
+
if (!this.staticAreaItem) {
|
|
799
|
+
this.staticAreaItem = StaticAreaItem.createInstance();
|
|
800
|
+
this.staticAreaItem.setOwnerElement(this);
|
|
818
801
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
if (slotsAreManaged) {
|
|
822
|
-
const slots = MetadataClass.getSlots();
|
|
823
|
-
for (const [slotName, slotData] of Object.entries(slots)) { // eslint-disable-line
|
|
824
|
-
const propertyName = slotData.propertyName || slotName;
|
|
825
|
-
defaultState[propertyName] = [];
|
|
826
|
-
}
|
|
802
|
+
if (!this.staticAreaItem.parentElement) {
|
|
803
|
+
getSingletonElementInstance("ui5-static-area").appendChild(this.staticAreaItem);
|
|
827
804
|
}
|
|
828
805
|
|
|
829
|
-
this.
|
|
830
|
-
return defaultState;
|
|
806
|
+
return this.staticAreaItem.getDomRef();
|
|
831
807
|
}
|
|
832
808
|
|
|
833
809
|
/**
|
|
@@ -841,7 +817,7 @@ class UI5Element extends HTMLElement {
|
|
|
841
817
|
const properties = this.getMetadata().getProperties();
|
|
842
818
|
for (const [prop, propData] of Object.entries(properties)) { // eslint-disable-line
|
|
843
819
|
if (!isValidPropertyName(prop)) {
|
|
844
|
-
|
|
820
|
+
console.warn(`"${prop}" is not a valid property name. Use a name that does not collide with DOM APIs`); /* eslint-disable-line */
|
|
845
821
|
}
|
|
846
822
|
|
|
847
823
|
if (propData.type === Boolean && propData.defaultValue) {
|
|
@@ -879,14 +855,27 @@ class UI5Element extends HTMLElement {
|
|
|
879
855
|
}
|
|
880
856
|
},
|
|
881
857
|
set(value) {
|
|
858
|
+
let isDifferent;
|
|
882
859
|
value = this.constructor.getMetadata().constructor.validatePropertyValue(value, propData);
|
|
883
860
|
|
|
884
861
|
const oldState = this._state[prop];
|
|
862
|
+
if (propData.multiple && propData.compareValues) {
|
|
863
|
+
isDifferent = !arraysAreEqual(oldState, value);
|
|
864
|
+
} else if (isDescendantOf(propData.type, DataType)) {
|
|
865
|
+
isDifferent = !propData.type.valuesAreEqual(oldState, value);
|
|
866
|
+
} else {
|
|
867
|
+
isDifferent = oldState !== value;
|
|
868
|
+
}
|
|
885
869
|
|
|
886
|
-
if (
|
|
870
|
+
if (isDifferent) {
|
|
887
871
|
this._state[prop] = value;
|
|
888
|
-
|
|
889
|
-
|
|
872
|
+
_invalidate.call(this, {
|
|
873
|
+
type: "property",
|
|
874
|
+
name: prop,
|
|
875
|
+
newValue: value,
|
|
876
|
+
oldValue: oldState,
|
|
877
|
+
});
|
|
878
|
+
this._updateAttribute(prop, value);
|
|
890
879
|
}
|
|
891
880
|
},
|
|
892
881
|
});
|
|
@@ -897,7 +886,7 @@ class UI5Element extends HTMLElement {
|
|
|
897
886
|
const slots = this.getMetadata().getSlots();
|
|
898
887
|
for (const [slotName, slotData] of Object.entries(slots)) { // eslint-disable-line
|
|
899
888
|
if (!isValidPropertyName(slotName)) {
|
|
900
|
-
|
|
889
|
+
console.warn(`"${slotName}" is not a valid property name. Use a name that does not collide with DOM APIs`); /* eslint-disable-line */
|
|
901
890
|
}
|
|
902
891
|
|
|
903
892
|
const propertyName = slotData.propertyName || slotName;
|
|
@@ -909,7 +898,7 @@ class UI5Element extends HTMLElement {
|
|
|
909
898
|
return [];
|
|
910
899
|
},
|
|
911
900
|
set() {
|
|
912
|
-
throw new Error("Cannot set
|
|
901
|
+
throw new Error("Cannot set slot content directly, use the DOM APIs (appendChild, removeChild, etc...)");
|
|
913
902
|
},
|
|
914
903
|
});
|
|
915
904
|
}
|
|
@@ -924,6 +913,14 @@ class UI5Element extends HTMLElement {
|
|
|
924
913
|
return metadata;
|
|
925
914
|
}
|
|
926
915
|
|
|
916
|
+
/**
|
|
917
|
+
* Sets a new metadata object for this UI5 Web Component Class
|
|
918
|
+
* @protected
|
|
919
|
+
*/
|
|
920
|
+
static set metadata(newMetadata) {
|
|
921
|
+
metadata = newMetadata;
|
|
922
|
+
}
|
|
923
|
+
|
|
927
924
|
/**
|
|
928
925
|
* Returns the CSS for this UI5 Web Component Class
|
|
929
926
|
* @protected
|
|
@@ -940,6 +937,50 @@ class UI5Element extends HTMLElement {
|
|
|
940
937
|
return "";
|
|
941
938
|
}
|
|
942
939
|
|
|
940
|
+
/**
|
|
941
|
+
* Returns an array with the dependencies for this UI5 Web Component, which could be:
|
|
942
|
+
* - composed components (used in its shadow root or static area item)
|
|
943
|
+
* - slotted components that the component may need to communicate with
|
|
944
|
+
*
|
|
945
|
+
* @protected
|
|
946
|
+
*/
|
|
947
|
+
static get dependencies() {
|
|
948
|
+
return [];
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
/**
|
|
952
|
+
* Returns a list of the unique dependencies for this UI5 Web Component
|
|
953
|
+
*
|
|
954
|
+
* @public
|
|
955
|
+
*/
|
|
956
|
+
static getUniqueDependencies() {
|
|
957
|
+
if (!uniqueDependenciesCache.has(this)) {
|
|
958
|
+
const filtered = this.dependencies.filter((dep, index, deps) => deps.indexOf(dep) === index);
|
|
959
|
+
uniqueDependenciesCache.set(this, filtered);
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
return uniqueDependenciesCache.get(this);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* Returns a promise that resolves whenever all dependencies for this UI5 Web Component have resolved
|
|
967
|
+
*
|
|
968
|
+
* @returns {Promise<any[]>}
|
|
969
|
+
*/
|
|
970
|
+
static whenDependenciesDefined() {
|
|
971
|
+
return Promise.all(this.getUniqueDependencies().map(dep => dep.define()));
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
/**
|
|
975
|
+
* Hook that will be called upon custom element definition
|
|
976
|
+
*
|
|
977
|
+
* @protected
|
|
978
|
+
* @returns {Promise<void>}
|
|
979
|
+
*/
|
|
980
|
+
static async onDefine() {
|
|
981
|
+
return Promise.resolve();
|
|
982
|
+
}
|
|
983
|
+
|
|
943
984
|
/**
|
|
944
985
|
* Registers a UI5 Web Component in the browser window object
|
|
945
986
|
* @public
|
|
@@ -948,9 +989,10 @@ class UI5Element extends HTMLElement {
|
|
|
948
989
|
static async define() {
|
|
949
990
|
await boot();
|
|
950
991
|
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
992
|
+
await Promise.all([
|
|
993
|
+
this.whenDependenciesDefined(),
|
|
994
|
+
this.onDefine(),
|
|
995
|
+
]);
|
|
954
996
|
|
|
955
997
|
const tag = this.getMetadata().getTag();
|
|
956
998
|
const altTag = this.getMetadata().getAltTag();
|
|
@@ -964,11 +1006,13 @@ class UI5Element extends HTMLElement {
|
|
|
964
1006
|
this._generateAccessors();
|
|
965
1007
|
registerTag(tag);
|
|
966
1008
|
window.customElements.define(tag, this);
|
|
1009
|
+
preloadLinks(this);
|
|
967
1010
|
|
|
968
1011
|
if (altTag && !customElements.get(altTag)) {
|
|
969
|
-
class oldClassName extends this {}
|
|
970
1012
|
registerTag(altTag);
|
|
971
|
-
window.customElements.define(altTag,
|
|
1013
|
+
window.customElements.define(altTag, getClassCopy(this, () => {
|
|
1014
|
+
console.log(`The ${altTag} tag is deprecated and will be removed in the next release, please use ${tag} instead.`); // eslint-disable-line
|
|
1015
|
+
}));
|
|
972
1016
|
}
|
|
973
1017
|
}
|
|
974
1018
|
return this;
|