@ui5/webcomponents-base 0.0.0-96e98c995 → 0.0.0-97cba4b0b

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.
Files changed (161) hide show
  1. package/.eslintignore +1 -0
  2. package/CHANGELOG.md +83 -0
  3. package/bundle.esm.js +3 -1
  4. package/dist/Boot.d.ts +4 -3
  5. package/dist/Boot.js +17 -4
  6. package/dist/Boot.js.map +1 -1
  7. package/dist/Device.js +109 -34
  8. package/dist/Device.js.map +1 -1
  9. package/dist/InitialConfiguration.js +1 -1
  10. package/dist/InitialConfiguration.js.map +1 -1
  11. package/dist/UI5Element.d.ts +20 -15
  12. package/dist/UI5Element.js +10 -22
  13. package/dist/UI5Element.js.map +1 -1
  14. package/dist/api.json +1 -1
  15. package/dist/asset-registries/Icons.d.ts +1 -1
  16. package/dist/asset-registries/Icons.js +21 -21
  17. package/dist/asset-registries/Icons.js.map +1 -1
  18. package/dist/asset-registries/Illustrations.d.ts +1 -1
  19. package/dist/asset-registries/Themes.d.ts +1 -0
  20. package/dist/assets/Boot.1c716721.js +9 -0
  21. package/dist/assets/Boot.6335ce08.css +1 -0
  22. package/dist/assets/bundle.esm.2f0ab67f.js +52 -0
  23. package/dist/assets-meta/IconCollectionsAlias.d.ts +24 -10
  24. package/dist/assets-meta/IconCollectionsAlias.js +29 -9
  25. package/dist/assets-meta/IconCollectionsAlias.js.map +1 -1
  26. package/dist/config/FormatSettings.d.ts +5 -1
  27. package/dist/config/FormatSettings.js +5 -1
  28. package/dist/config/FormatSettings.js.map +1 -1
  29. package/dist/config/Icons.d.ts +43 -18
  30. package/dist/config/Icons.js +80 -25
  31. package/dist/config/Icons.js.map +1 -1
  32. package/dist/config/RTL.js +3 -0
  33. package/dist/config/RTL.js.map +1 -1
  34. package/dist/decorators/customElement.d.ts +17 -2
  35. package/dist/decorators/customElement.js +20 -5
  36. package/dist/decorators/customElement.js.map +1 -1
  37. package/dist/decorators/event.js +6 -6
  38. package/dist/decorators/event.js.map +1 -1
  39. package/dist/decorators/property.js +6 -6
  40. package/dist/decorators/property.js.map +1 -1
  41. package/dist/decorators/slot.js +7 -7
  42. package/dist/decorators/slot.js.map +1 -1
  43. package/dist/delegate/ResizeHandler.d.ts +2 -1
  44. package/dist/delegate/ResizeHandler.js +3 -1
  45. package/dist/delegate/ResizeHandler.js.map +1 -1
  46. package/dist/features/F6Navigation.d.ts +3 -0
  47. package/dist/features/F6Navigation.js +77 -38
  48. package/dist/features/F6Navigation.js.map +1 -1
  49. package/dist/features/LegacyDateFormats.d.ts +18 -0
  50. package/dist/features/LegacyDateFormats.js +20 -0
  51. package/dist/features/LegacyDateFormats.js.map +1 -0
  52. package/dist/features/OpenUI5Support.d.ts +2 -0
  53. package/dist/features/OpenUI5Support.js +1 -0
  54. package/dist/features/OpenUI5Support.js.map +1 -1
  55. package/dist/generated/VersionInfo.js +3 -3
  56. package/dist/generated/css/BusyIndicator.css.d.ts +3 -0
  57. package/dist/generated/css/BusyIndicator.css.js +7 -5
  58. package/dist/generated/css/BusyIndicator.css.js.map +1 -0
  59. package/dist/generated/css/FontFace.css.d.ts +3 -0
  60. package/dist/generated/css/FontFace.css.js +7 -5
  61. package/dist/generated/css/FontFace.css.js.map +1 -0
  62. package/dist/generated/css/OverrideFontFace.css.d.ts +3 -0
  63. package/dist/generated/css/OverrideFontFace.css.js +7 -5
  64. package/dist/generated/css/OverrideFontFace.css.js.map +1 -0
  65. package/dist/generated/css/SystemCSSVars.css.d.ts +3 -0
  66. package/dist/generated/css/SystemCSSVars.css.js +7 -5
  67. package/dist/generated/css/SystemCSSVars.css.js.map +1 -0
  68. package/dist/getSharedResource.js +9 -1
  69. package/dist/getSharedResource.js.map +1 -1
  70. package/dist/global.d.ts +0 -6
  71. package/dist/renderer/LitRenderer.d.ts +3 -3
  72. package/dist/renderer/LitRenderer.js.map +1 -1
  73. package/dist/theming/CustomStyle.js +7 -5
  74. package/dist/theming/CustomStyle.js.map +1 -1
  75. package/dist/theming/getStylesString.d.ts +1 -1
  76. package/dist/types/AnimationMode.d.ts +1 -1
  77. package/dist/types/AnimationMode.js +1 -1
  78. package/dist/types/CSSColor.d.ts +0 -1
  79. package/dist/types/CSSColor.js +0 -1
  80. package/dist/types/CSSColor.js.map +1 -1
  81. package/dist/types/CalendarType.d.ts +1 -1
  82. package/dist/types/CalendarType.js +1 -1
  83. package/dist/types/Float.d.ts +0 -1
  84. package/dist/types/Float.js +0 -1
  85. package/dist/types/Float.js.map +1 -1
  86. package/dist/types/Integer.d.ts +0 -1
  87. package/dist/types/Integer.js +0 -1
  88. package/dist/types/Integer.js.map +1 -1
  89. package/dist/types/InvisibleMessageMode.d.ts +1 -1
  90. package/dist/types/InvisibleMessageMode.js +1 -1
  91. package/dist/types/ItemNavigationBehavior.d.ts +1 -1
  92. package/dist/types/ItemNavigationBehavior.js +1 -1
  93. package/dist/types/NavigationMode.d.ts +1 -1
  94. package/dist/types/NavigationMode.js +1 -1
  95. package/dist/types/ValueState.d.ts +1 -1
  96. package/dist/types/ValueState.js +1 -1
  97. package/dist/updateShadowRoot.js +4 -0
  98. package/dist/updateShadowRoot.js.map +1 -1
  99. package/dist/util/AriaLabelHelper.d.ts +10 -1
  100. package/dist/util/AriaLabelHelper.js +135 -8
  101. package/dist/util/AriaLabelHelper.js.map +1 -1
  102. package/dist/util/FocusableElements.js +11 -2
  103. package/dist/util/FocusableElements.js.map +1 -1
  104. package/dist/util/getClassCopy.d.ts +8 -10
  105. package/lib/generate-styles/index.js +10 -5
  106. package/package-scripts.js +8 -4
  107. package/package.json +2 -2
  108. package/src/Boot.ts +20 -5
  109. package/src/Device.ts +113 -34
  110. package/src/InitialConfiguration.ts +1 -1
  111. package/src/UI5Element.ts +31 -27
  112. package/src/asset-registries/Icons.ts +26 -27
  113. package/src/asset-registries/Illustrations.ts +1 -1
  114. package/src/asset-registries/Themes.ts +5 -0
  115. package/src/assets-meta/IconCollectionsAlias.ts +32 -9
  116. package/src/config/FormatSettings.ts +16 -2
  117. package/src/config/Icons.ts +92 -25
  118. package/src/config/RTL.ts +4 -0
  119. package/src/decorators/customElement.ts +45 -5
  120. package/src/decorators/event.ts +6 -6
  121. package/src/decorators/property.ts +6 -6
  122. package/src/decorators/slot.ts +7 -7
  123. package/src/delegate/ResizeHandler.ts +7 -2
  124. package/src/features/F6Navigation.ts +98 -44
  125. package/src/features/LegacyDateFormats.ts +40 -0
  126. package/src/features/OpenUI5Support.ts +5 -0
  127. package/src/generated/css/BusyIndicator.css.ts +9 -0
  128. package/src/generated/css/FontFace.css.ts +9 -0
  129. package/src/generated/css/OverrideFontFace.css.ts +9 -0
  130. package/src/generated/css/SystemCSSVars.css.ts +9 -0
  131. package/src/getSharedResource.ts +10 -1
  132. package/src/global.d.ts +0 -6
  133. package/src/renderer/LitRenderer.ts +2 -2
  134. package/src/theming/CustomStyle.ts +7 -5
  135. package/src/theming/getEffectiveLinksHrefs.ts +1 -1
  136. package/src/theming/getStylesString.ts +1 -1
  137. package/src/types/AnimationMode.ts +1 -1
  138. package/src/types/CSSColor.ts +0 -1
  139. package/src/types/CalendarType.ts +1 -1
  140. package/src/types/Float.ts +0 -1
  141. package/src/types/Integer.ts +0 -1
  142. package/src/types/InvisibleMessageMode.ts +1 -1
  143. package/src/types/ItemNavigationBehavior.ts +1 -1
  144. package/src/types/NavigationMode.ts +1 -1
  145. package/src/types/ValueState.ts +1 -1
  146. package/src/updateShadowRoot.ts +5 -0
  147. package/src/util/AriaLabelHelper.ts +167 -12
  148. package/src/util/FocusableElements.ts +12 -2
  149. package/dist/assets/bundle.esm.ba5d36d4.js +0 -56
  150. package/dist/decorators/fastNavigation.d.ts +0 -7
  151. package/dist/decorators/fastNavigation.js +0 -13
  152. package/dist/decorators/fastNavigation.js.map +0 -1
  153. package/dist/decorators/languageAware.d.ts +0 -7
  154. package/dist/decorators/languageAware.js +0 -13
  155. package/dist/decorators/languageAware.js.map +0 -1
  156. package/dist/decorators/themeAware.d.ts +0 -7
  157. package/dist/decorators/themeAware.js +0 -13
  158. package/dist/decorators/themeAware.js.map +0 -1
  159. package/src/decorators/fastNavigation.ts +0 -14
  160. package/src/decorators/languageAware.ts +0 -14
  161. package/src/decorators/themeAware.ts +0 -14
@@ -1,6 +1,11 @@
1
1
  import getSingletonElementInstance from "./util/getSingletonElementInstance.js";
2
2
 
3
- const getSharedResourcesInstance = () => getSingletonElementInstance("ui5-shared-resources", document.head);
3
+ const getSharedResourcesInstance = (): Record<string, unknown> | null => {
4
+ if (typeof document === "undefined") {
5
+ return null;
6
+ }
7
+ return getSingletonElementInstance("ui5-shared-resources", document.head) as unknown as Record<string, unknown>;
8
+ };
4
9
 
5
10
  /**
6
11
  * Use this method to initialize/get resources that you would like to be shared among UI5 Web Components runtime instances.
@@ -15,6 +20,10 @@ const getSharedResource = <T>(namespace: string, initialValue: T): T => {
15
20
  const parts = namespace.split(".");
16
21
  let current = getSharedResourcesInstance() as Record<string, any>;
17
22
 
23
+ if (!current) {
24
+ return initialValue;
25
+ }
26
+
18
27
  for (let i = 0; i < parts.length; i++) {
19
28
  const part = parts[i];
20
29
  const lastPart = i === parts.length - 1;
package/src/global.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { StyleData } from "./types.js";
2
-
3
1
  export {};
4
2
 
5
3
  declare global {
@@ -19,10 +17,6 @@ declare global {
19
17
  chrome: any;
20
18
  v8: any;
21
19
  }
22
- module "*.css.js" {
23
- const content: StyleData;
24
- export default content;
25
- }
26
20
 
27
21
  module "*generated/AssetParameters.js" {
28
22
  const DEFAULT_THEME: string;
@@ -3,13 +3,13 @@ import {
3
3
  html,
4
4
  svg,
5
5
  TemplateResult,
6
- RenderOptions,
7
6
  } from "lit-html";
8
7
 
9
8
  import { getFeature } from "../FeaturesRegistry.js";
10
9
  import type { LitStatic } from "../CustomElementsScope.js";
11
10
  import type OpenUI5Enablement from "../features/OpenUI5Enablement.js";
12
11
  import type UI5Element from "../UI5Element.js";
12
+ import type { Renderer, RendererOptions } from "../UI5Element.js";
13
13
  import { TemplateFunctionResult } from "./executeTemplate.js";
14
14
 
15
15
  const effectiveHtml = (strings: TemplateStringsArray, ...values: Array<unknown>) => {
@@ -24,7 +24,7 @@ const effectiveSvg = (strings: TemplateStringsArray, ...values: Array<unknown>)
24
24
  return fn(strings, ...values);
25
25
  };
26
26
 
27
- const litRender = (templateResult: TemplateFunctionResult, container: HTMLElement | DocumentFragment, styleStrOrHrefsArr: string | Array<string> | undefined, forStaticArea: boolean, options: RenderOptions) => {
27
+ const litRender: Renderer = (templateResult: TemplateFunctionResult, container: HTMLElement | DocumentFragment, styleStrOrHrefsArr: string | Array<string> | undefined, forStaticArea: boolean, options: RendererOptions) => {
28
28
  const openUI5Enablement = getFeature<typeof OpenUI5Enablement>("OpenUI5Enablement");
29
29
  if (openUI5Enablement && !forStaticArea) {
30
30
  templateResult = openUI5Enablement.wrapTemplateResultInBusyMarkup(effectiveHtml, options.host as UI5Element, templateResult as TemplateResult);
@@ -4,22 +4,22 @@ import EventProvider from "../EventProvider.js";
4
4
 
5
5
  type CustomCSSChangeCallback = (tag: string) => void;
6
6
 
7
- const eventProvider = getSharedResource("CustomStyle.eventProvider", new EventProvider<string, void>());
7
+ const getEventProvider = () => getSharedResource("CustomStyle.eventProvider", new EventProvider<string, void>());
8
8
  const CUSTOM_CSS_CHANGE = "CustomCSSChange";
9
9
 
10
10
  const attachCustomCSSChange = (listener: CustomCSSChangeCallback) => {
11
- eventProvider.attachEvent(CUSTOM_CSS_CHANGE, listener);
11
+ getEventProvider().attachEvent(CUSTOM_CSS_CHANGE, listener);
12
12
  };
13
13
 
14
14
  const detachCustomCSSChange = (listener: CustomCSSChangeCallback) => {
15
- eventProvider.detachEvent(CUSTOM_CSS_CHANGE, listener);
15
+ getEventProvider().detachEvent(CUSTOM_CSS_CHANGE, listener);
16
16
  };
17
17
 
18
18
  const fireCustomCSSChange = (tag: string) => {
19
- return eventProvider.fireEvent(CUSTOM_CSS_CHANGE, tag);
19
+ return getEventProvider().fireEvent(CUSTOM_CSS_CHANGE, tag);
20
20
  };
21
21
 
22
- const customCSSFor = getSharedResource<Record<string, Array<string>>>("CustomStyle.customCSSFor", {});
22
+ const getCustomCSSFor = () => getSharedResource<Record<string, Array<string>>>("CustomStyle.customCSSFor", {});
23
23
 
24
24
  // Listen to the eventProvider, in case other copies of this CustomStyle module fire this
25
25
  // event, and this copy would therefore need to reRender the ui5 webcomponents; but
@@ -32,6 +32,7 @@ attachCustomCSSChange((tag: string) => {
32
32
  });
33
33
 
34
34
  const addCustomCSS = (tag: string, css: string) => {
35
+ const customCSSFor = getCustomCSSFor();
35
36
  if (!customCSSFor[tag]) {
36
37
  customCSSFor[tag] = [];
37
38
  }
@@ -51,6 +52,7 @@ const addCustomCSS = (tag: string, css: string) => {
51
52
  };
52
53
 
53
54
  const getCustomCSS = (tag: string) => {
55
+ const customCSSFor = getCustomCSSFor();
54
56
  return customCSSFor[tag] ? customCSSFor[tag].join("") : "";
55
57
  };
56
58
 
@@ -2,7 +2,7 @@ import { getUrl } from "../CSP.js";
2
2
  import { getFeature } from "../FeaturesRegistry.js";
3
3
  import type UI5Element from "../UI5Element.js";
4
4
  import type OpenUI5Enablement from "../features/OpenUI5Enablement.js";
5
- import { ComponentStylesData, StyleDataCSP } from "../types.js";
5
+ import type { ComponentStylesData, StyleDataCSP } from "../types.js";
6
6
 
7
7
  const MAX_DEPTH_INHERITED_CLASSES = 10; // TypeScript complains about Infinity and big numbers
8
8
 
@@ -1,4 +1,4 @@
1
- import { ComponentStylesData, StyleData } from "../types.js";
1
+ import type { ComponentStylesData, StyleData } from "../types.js";
2
2
 
3
3
  const MAX_DEPTH_INHERITED_CLASSES = 10; // TypeScript complains about Infinity and big numbers
4
4
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Different types of AnimationMode.
3
3
  *
4
- * @class
4
+ * @readonly
5
5
  * @enum {string}
6
6
  * @public
7
7
  * @author SAP SE
@@ -9,7 +9,6 @@ import DataType from "./DataType.js";
9
9
  * @author SAP SE
10
10
  * @alias sap.ui.webc.base.types.CSSColor
11
11
  * @public
12
- * @enum {string}
13
12
  */
14
13
  class CSSColor extends DataType {
15
14
  static override isValid(value: string) {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Different calendar types.
3
3
  *
4
- * @class
4
+ * @readonly
5
5
  * @enum {string}
6
6
  * @public
7
7
  * @author SAP SE
@@ -10,7 +10,6 @@ import DataType from "./DataType.js";
10
10
  * @author SAP SE
11
11
  * @alias sap.ui.webc.base.types.Float
12
12
  * @public
13
- * @enum {number}
14
13
  */
15
14
  class Float extends DataType {
16
15
  static override isValid(value: any) {
@@ -10,7 +10,6 @@ import DataType from "./DataType.js";
10
10
  * @author SAP SE
11
11
  * @alias sap.ui.webc.base.types.Integer
12
12
  * @public
13
- * @enum {number}
14
13
  */
15
14
  class Integer extends DataType {
16
15
  static override isValid(value: any) {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Enumeration for different mode behaviors of the InvisibleMessage.
3
3
  *
4
- * @class
4
+ * @readonly
5
5
  * @enum {string}
6
6
  * @public
7
7
  * @author SAP SE
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Different behavior for ItemNavigation.
3
3
  *
4
- * @class
4
+ * @readonly
5
5
  * @enum {string}
6
6
  * @public
7
7
  * @author SAP SE
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Different navigation modes for ItemNavigation.
3
3
  *
4
- * @class
4
+ * @readonly
5
5
  * @enum {string}
6
6
  * @public
7
7
  * @author SAP SE
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Different types of ValueStates.
3
3
  *
4
- * @class
4
+ * @readonly
5
5
  * @enum {string}
6
6
  * @public
7
7
  * @author SAP SE
@@ -31,6 +31,11 @@ const updateShadowRoot = (element: UI5Element, forStaticArea = false) => {
31
31
  styleStrOrHrefsArr = getEffectiveStyle(ctor, forStaticArea);
32
32
  }
33
33
 
34
+ if (ctor.renderer) {
35
+ ctor.renderer(renderResult, shadowRoot, styleStrOrHrefsArr, forStaticArea, { host: element });
36
+ return;
37
+ }
38
+
34
39
  ctor.render(renderResult, shadowRoot, styleStrOrHrefsArr, forStaticArea, { host: element });
35
40
  };
36
41
 
@@ -1,7 +1,32 @@
1
+ import UI5Element, { ChangeInfo } from "../UI5Element.js";
2
+
3
+ type InvalidateCallback = (changeInfo: ChangeInfo) => void;
4
+ type MutationCallback = () => void;
5
+ type AssociatedElement = {
6
+ observer: MutationObserver | null;
7
+ callbacks: Array<MutationCallback>;
8
+ };
9
+ type RegisteredElement = {
10
+ host: UI5Element;
11
+ observedElements: Array<HTMLElement>;
12
+ callback: MutationCallback;
13
+ invalidationCallback: InvalidateCallback;
14
+ };
15
+
16
+ const associatedElements = new WeakMap<HTMLElement, AssociatedElement>();
17
+ const registeredElements = new WeakMap<UI5Element, RegisteredElement>();
18
+
1
19
  type AccessibleElement = HTMLElement & {
2
- accessibleNameRef: string,
3
- accessibleName: string,
4
- }
20
+ accessibleNameRef: string;
21
+ accessibleName: string;
22
+ };
23
+
24
+ const observerOptions = {
25
+ attributes: true,
26
+ childList: true,
27
+ characterData: true,
28
+ subtree: true,
29
+ };
5
30
 
6
31
  const getEffectiveAriaLabelText = (el: HTMLElement) => {
7
32
  const accessibleEl = el as AccessibleElement;
@@ -14,38 +39,68 @@ const getEffectiveAriaLabelText = (el: HTMLElement) => {
14
39
  return undefined;
15
40
  }
16
41
 
17
- return _getAriaLabelledByTexts(el);
42
+ return getAllAccessibleNameRefTexts(el);
18
43
  };
19
44
 
20
45
  /**
21
46
  *
22
47
  * @param {HTMLElement} el Defines the HTMLElement, for which you need to get all related texts
23
48
  */
24
- const _getAriaLabelledByTexts = (el: HTMLElement) => {
25
- const ids = (el as AccessibleElement).accessibleNameRef.split(" ");
49
+ const getAllAccessibleNameRefTexts = (el: HTMLElement) => {
50
+ const ids = (el as AccessibleElement).accessibleNameRef?.split(" ") ?? [];
26
51
  const owner = el.getRootNode() as HTMLElement;
27
52
  let result = "";
28
53
 
29
54
  ids.forEach((elementId: string, index: number) => {
30
55
  const element = owner.querySelector(`[id='${elementId}']`);
31
- result += `${element && element.textContent ? element.textContent : ""}`;
32
-
33
- if (index < ids.length - 1) {
34
- result += " ";
56
+ const text = `${element && element.textContent ? element.textContent : ""}`;
57
+ if (text) {
58
+ result += text;
59
+ if (index < ids.length - 1) {
60
+ result += " ";
61
+ }
35
62
  }
36
63
  });
37
64
 
38
65
  return result;
39
66
  };
40
67
 
68
+ const _getAllAssociatedElementsFromDOM = (el: UI5Element): Array<HTMLElement> => {
69
+ const set = new Set<HTMLElement>();
70
+ // adding labels with attribute for matching the el.id
71
+ const labelsForAssociated = _getAssociatedLabels(el);
72
+ labelsForAssociated.forEach(itm => {
73
+ set.add(itm);
74
+ });
75
+ // adding other elements that id is the same as accessibleNameRef value
76
+ const value = el["accessibleNameRef" as keyof typeof el] as string;
77
+ const ids = value?.split(" ") ?? [];
78
+ ids.forEach(id => {
79
+ const refEl = _getReferencedElementById(el, id);
80
+ if (refEl) {
81
+ set.add(refEl);
82
+ }
83
+ });
84
+ return Array.from(set);
85
+ };
86
+
87
+ const _getAssociatedLabels = (el: HTMLElement): Array<HTMLElement> => {
88
+ const labels = (el.getRootNode() as HTMLElement).querySelectorAll<HTMLElement>(`[for="${el.id}"]`);
89
+ return Array.from(labels);
90
+ };
91
+
92
+ const _getReferencedElementById = (el: HTMLElement, elementId: string): HTMLElement | null => {
93
+ return (el.getRootNode() as HTMLElement).querySelector<HTMLElement>(`[id='${elementId}']`);
94
+ };
95
+
41
96
  /**
42
97
  * @param {HTMLElement} el Defines the HTMLElement, for which you need to get all related "label for" texts
43
98
  */
44
99
  const getAssociatedLabelForTexts = (el: HTMLElement) => {
45
100
  const results: Array<string> = [];
46
- const labels = (el.getRootNode() as HTMLElement).querySelectorAll(`[ui5-label][for="${el.id}"],label[for="${el.id}"]`);
101
+ const labels = _getAssociatedLabels(el);
47
102
 
48
- labels.forEach((label: Node) => {
103
+ labels.forEach((label: HTMLElement) => {
49
104
  const labelText = label.textContent;
50
105
  labelText && results.push(labelText);
51
106
  });
@@ -57,7 +112,107 @@ const getAssociatedLabelForTexts = (el: HTMLElement) => {
57
112
  return undefined;
58
113
  };
59
114
 
115
+ const _createInvalidationCallback = (el: UI5Element) => {
116
+ const invalidationCallback = (changeInfo: ChangeInfo) => {
117
+ if (!(changeInfo && changeInfo.type === "property" && changeInfo.name === "accessibleNameRef")) {
118
+ return;
119
+ }
120
+ const registeredElement = registeredElements.get(el);
121
+ if (!registeredElement) {
122
+ return;
123
+ }
124
+ const oldAssociatedElements = registeredElement.observedElements;
125
+ const newAssociatedElements = _getAllAssociatedElementsFromDOM(el);
126
+ oldAssociatedElements.forEach(oldElement => {
127
+ if (!newAssociatedElements.includes(oldElement)) {
128
+ _removeObservedElementFromRegisteredElement(registeredElement, oldElement);
129
+ }
130
+ });
131
+ newAssociatedElements.forEach(newElement => {
132
+ if (!oldAssociatedElements.includes(newElement)) {
133
+ _addObservedElementToRegisteredElement(registeredElement, newElement);
134
+ registeredElement.observedElements.push(newElement);
135
+ }
136
+ });
137
+ registeredElement?.callback();
138
+ };
139
+ return invalidationCallback;
140
+ };
141
+
142
+ const registerUI5Element = (el: UI5Element, callback: MutationCallback) => {
143
+ if (registeredElements.has(el)) {
144
+ return;
145
+ }
146
+ const allAssociatedElements = _getAllAssociatedElementsFromDOM(el);
147
+ const invalidationCallback = _createInvalidationCallback(el);
148
+ const registeredElement = {
149
+ host: el,
150
+ observedElements: allAssociatedElements,
151
+ callback,
152
+ invalidationCallback,
153
+ };
154
+ registeredElements.set(el, registeredElement);
155
+ el.attachInvalidate(invalidationCallback);
156
+
157
+ allAssociatedElements.forEach((element: HTMLElement) => {
158
+ _addObservedElementToRegisteredElement(registeredElement, element);
159
+ });
160
+ callback();
161
+ };
162
+
163
+ const _addObservedElementToRegisteredElement = (registeredElement: RegisteredElement, element: HTMLElement) => {
164
+ let associatedElement = associatedElements.get(element);
165
+ if (!associatedElement) {
166
+ associatedElement = { observer: null, callbacks: [] };
167
+ const observer = new MutationObserver(() => {
168
+ const callbacks = (associatedElement as AssociatedElement).callbacks;
169
+ callbacks.forEach(callback => {
170
+ callback();
171
+ });
172
+ const domEl = document.getElementById(element.id);
173
+ // if no longer should be observed from this registeredElement, remove it
174
+ if (!(registeredElement.host.id === element.getAttribute("for") || domEl)) {
175
+ _removeObservedElementFromRegisteredElement(registeredElement, element);
176
+ }
177
+ });
178
+ associatedElement.observer = observer;
179
+ observer.observe(element, observerOptions);
180
+ associatedElements.set(element, associatedElement);
181
+ }
182
+ if (!associatedElement.callbacks.includes(registeredElement.callback)) {
183
+ associatedElement.callbacks.push(registeredElement.callback);
184
+ }
185
+ };
186
+
187
+ const _removeObservedElementFromRegisteredElement = (registeredElement: RegisteredElement, element: HTMLElement) => {
188
+ const associatedElement = associatedElements.get(element);
189
+ if (associatedElement) {
190
+ associatedElement.callbacks = associatedElement.callbacks.filter(itm => itm !== registeredElement.callback);
191
+ if (!associatedElement.callbacks.length) {
192
+ associatedElement.observer?.disconnect();
193
+ associatedElements.delete(element);
194
+ }
195
+ }
196
+ registeredElement.observedElements = registeredElement.observedElements.filter(itm => itm !== element);
197
+ };
198
+
199
+ const deregisterUI5Element = (el: UI5Element) => {
200
+ const registeredElement = registeredElements.get(el);
201
+ if (!registeredElement) {
202
+ return;
203
+ }
204
+ const oldObservedElements = [...registeredElement.observedElements];
205
+ oldObservedElements.forEach(observedElement => {
206
+ _removeObservedElementFromRegisteredElement(registeredElement, observedElement);
207
+ });
208
+ el.detachInvalidate(registeredElement.invalidationCallback);
209
+ registeredElements.delete(el);
210
+ };
211
+
60
212
  export {
61
213
  getEffectiveAriaLabelText,
62
214
  getAssociatedLabelForTexts,
215
+ registerUI5Element,
216
+ deregisterUI5Element,
217
+ getAllAccessibleNameRefTexts,
63
218
  };
@@ -30,12 +30,15 @@ const isElemFocusable = (el: HTMLElement) => {
30
30
 
31
31
  const findFocusableElement = async (container: HTMLElement, forward: boolean, startFromContainer?: boolean): FocusableElementPromise => {
32
32
  let child: HTMLElement | undefined;
33
+ let assignedElements;
34
+ let currentIndex = -1;
33
35
 
34
36
  if (container.shadowRoot) {
35
37
  child = forward ? container.shadowRoot.firstChild as HTMLElement : container.shadowRoot.lastChild as HTMLElement;
36
38
  } else if (container instanceof HTMLSlotElement && container.assignedNodes()) {
37
- const assignedElements = container.assignedNodes();
38
- child = forward ? assignedElements[0] as HTMLElement : assignedElements[assignedElements.length - 1] as HTMLElement;
39
+ assignedElements = container.assignedNodes();
40
+ currentIndex = forward ? 0 : assignedElements.length - 1;
41
+ child = assignedElements[currentIndex] as HTMLElement;
39
42
  } else if (startFromContainer) {
40
43
  child = container;
41
44
  } else {
@@ -69,6 +72,13 @@ const findFocusableElement = async (container: HTMLElement, forward: boolean, st
69
72
  }
70
73
 
71
74
  child = forward ? originalChild.nextSibling as HTMLElement : originalChild.previousSibling as HTMLElement;
75
+
76
+ // If the child element is not part of the currently assigned element,
77
+ // we have to check the next element assigned to the slot or continue with the next sibling of the slot,
78
+ // otherwise, the nextSibling is the next element inside the light DOM
79
+ if (assignedElements && !assignedElements[currentIndex].contains(child)) {
80
+ child = assignedElements[++currentIndex] as HTMLElement;
81
+ }
72
82
  }
73
83
 
74
84
  /* eslint-enable no-await-in-loop */