@sapudex/web-components 2.57.0 → 2.58.0
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/cypress/specs/FilterMenu.cy.tsx +209 -19
- package/cypress/specs/List.cy.tsx +67 -4
- package/cypress/specs/ListItem.cy.tsx +35 -9
- package/cypress/specs/SelectBox.cy.tsx +100 -0
- package/cypress/specs/TabNavigation.cy.tsx +297 -21
- package/dist/List.d.ts +15 -1
- package/dist/List.js +23 -2
- package/dist/List.js.map +1 -1
- package/dist/ListGroupHeaderBase.d.ts +13 -0
- package/dist/ListGroupHeaderBase.js +43 -2
- package/dist/ListGroupHeaderBase.js.map +1 -1
- package/dist/ListGroupHeaderTemplate.js +26 -7
- package/dist/ListGroupHeaderTemplate.js.map +1 -1
- package/dist/ListItem.d.ts +0 -3
- package/dist/ListItem.js +18 -12
- package/dist/ListItem.js.map +1 -1
- package/dist/ListItemBase.d.ts +17 -0
- package/dist/ListItemBase.js +15 -0
- package/dist/ListItemBase.js.map +1 -1
- package/dist/ListItemTemplate.js +2 -2
- package/dist/ListItemTemplate.js.map +1 -1
- package/dist/MastheadCountrySelector.js +5 -5
- package/dist/MastheadCountrySelector.js.map +1 -1
- package/dist/MastheadCountrySelectorTemplate.d.ts +2 -0
- package/dist/MastheadCountrySelectorTemplate.js +15 -0
- package/dist/MastheadCountrySelectorTemplate.js.map +1 -0
- package/dist/MastheadItem.d.ts +0 -3
- package/dist/MastheadItem.js +3 -6
- package/dist/MastheadItem.js.map +1 -1
- package/dist/MastheadItemTemplate.d.ts +2 -0
- package/dist/MastheadItemTemplate.js +41 -0
- package/dist/MastheadItemTemplate.js.map +1 -0
- package/dist/MastheadMenu.d.ts +1 -0
- package/dist/MastheadMenu.js +4 -6
- package/dist/MastheadMenu.js.map +1 -1
- package/dist/MastheadMenuItem.d.ts +0 -3
- package/dist/MastheadMenuItem.js +3 -6
- package/dist/MastheadMenuItem.js.map +1 -1
- package/dist/MastheadMenuItemTemplate.d.ts +2 -0
- package/dist/MastheadMenuItemTemplate.js +36 -0
- package/dist/MastheadMenuItemTemplate.js.map +1 -0
- package/dist/MastheadMenuTemplate.d.ts +2 -0
- package/dist/MastheadMenuTemplate.js +13 -0
- package/dist/MastheadMenuTemplate.js.map +1 -0
- package/dist/MastheadMobileMenu.js +3 -3
- package/dist/MastheadMobileMenu.js.map +1 -1
- package/dist/MastheadMobileMenuTemplate.d.ts +2 -0
- package/dist/MastheadMobileMenuTemplate.js +33 -0
- package/dist/MastheadMobileMenuTemplate.js.map +1 -0
- package/dist/MastheadProfileMenu.d.ts +2 -4
- package/dist/MastheadProfileMenu.js +5 -20
- package/dist/MastheadProfileMenu.js.map +1 -1
- package/dist/MastheadProfileMenuTemplate.d.ts +2 -0
- package/dist/MastheadProfileMenuTemplate.js +24 -0
- package/dist/MastheadProfileMenuTemplate.js.map +1 -0
- package/dist/MastheadShell.js +3 -5
- package/dist/MastheadShell.js.map +1 -1
- package/dist/MastheadShellTemplate.d.ts +2 -0
- package/dist/MastheadShellTemplate.js +20 -0
- package/dist/MastheadShellTemplate.js.map +1 -0
- package/dist/SearchableListBase.d.ts +10 -0
- package/dist/SearchableListBase.js +34 -1
- package/dist/SearchableListBase.js.map +1 -1
- package/dist/SearchableListBaseTemplate.js +35 -4
- package/dist/SearchableListBaseTemplate.js.map +1 -1
- package/dist/SecondaryNavigation.d.ts +1 -0
- package/dist/SecondaryNavigation.js +20 -6
- package/dist/SecondaryNavigation.js.map +1 -1
- package/dist/SelectBase.js +8 -3
- package/dist/SelectBase.js.map +1 -1
- package/dist/Tab.d.ts +0 -7
- package/dist/Tab.js +4 -19
- package/dist/Tab.js.map +1 -1
- package/dist/TabHeaderTemplate.d.ts +2 -0
- package/dist/TabHeaderTemplate.js +15 -0
- package/dist/TabHeaderTemplate.js.map +1 -0
- package/dist/TabInOverflowTemplate.d.ts +2 -0
- package/dist/TabInOverflowTemplate.js +7 -0
- package/dist/TabInOverflowTemplate.js.map +1 -0
- package/dist/TabNavigation.d.ts +3 -4
- package/dist/TabNavigation.js +53 -40
- package/dist/TabNavigation.js.map +1 -1
- package/dist/TabNavigationPopoverTemplate.d.ts +2 -0
- package/dist/TabNavigationPopoverTemplate.js +9 -0
- package/dist/TabNavigationPopoverTemplate.js.map +1 -0
- package/dist/TabNavigationTemplate.d.ts +2 -0
- package/dist/TabNavigationTemplate.js +10 -0
- package/dist/TabNavigationTemplate.js.map +1 -0
- package/dist/TabTemplate.d.ts +2 -0
- package/dist/TabTemplate.js +5 -0
- package/dist/TabTemplate.js.map +1 -0
- package/dist/assets/{InputSuggestions-C8grDr_8.js → InputSuggestions-CMYjJsHw.js} +1 -1
- package/dist/assets/{ListItemStandardExpandableTextTemplate-BQtSr7yg.js → ListItemStandardExpandableTextTemplate-D2i8wWuR.js} +1 -1
- package/dist/assets/{bundle.esm-GvPkDyXP.js → bundle.esm-BjN47C_y.js} +242 -242
- package/dist/assets/messagebundle_en-B7YJOdQz.js +1 -0
- package/dist/css/themes/Button.css +1 -1
- package/dist/css/themes/ListGroupHeader.css +1 -1
- package/dist/css/themes/PromoTile.css +1 -1
- package/dist/css/themes/TabInOverflow.css +1 -1
- package/dist/generated/assets/i18n/messagebundle_en.json +1 -1
- package/dist/generated/i18n/i18n-defaults.d.ts +3 -1
- package/dist/generated/i18n/i18n-defaults.js +3 -1
- package/dist/generated/i18n/i18n-defaults.js.map +1 -1
- package/dist/generated/themes/Button.css.d.ts +1 -1
- package/dist/generated/themes/Button.css.js +1 -1
- package/dist/generated/themes/Button.css.js.map +1 -1
- package/dist/generated/themes/ListGroupHeader.css.d.ts +1 -1
- package/dist/generated/themes/ListGroupHeader.css.js +1 -1
- package/dist/generated/themes/ListGroupHeader.css.js.map +1 -1
- package/dist/generated/themes/PromoTile.css.d.ts +1 -1
- package/dist/generated/themes/PromoTile.css.js +1 -1
- package/dist/generated/themes/PromoTile.css.js.map +1 -1
- package/dist/generated/themes/TabInOverflow.css.d.ts +1 -1
- package/dist/generated/themes/TabInOverflow.css.js +1 -1
- package/dist/generated/themes/TabInOverflow.css.js.map +1 -1
- package/dist/messagebundle.properties +4 -0
- package/dist/messagebundle_en.properties +2 -0
- package/dist/web-types.json +1 -1
- package/package.json +1 -1
- package/src/List.ts +24 -2
- package/src/ListGroupHeaderBase.ts +44 -2
- package/src/ListGroupHeaderTemplate.tsx +74 -23
- package/src/ListItem.ts +18 -15
- package/src/ListItemBase.ts +30 -0
- package/src/ListItemTemplate.tsx +4 -4
- package/src/MastheadCountrySelector.ts +5 -5
- package/src/MastheadCountrySelectorTemplate.tsx +98 -0
- package/src/MastheadItem.ts +3 -6
- package/src/MastheadItemTemplate.tsx +178 -0
- package/src/MastheadMenu.ts +5 -6
- package/src/MastheadMenuItem.ts +3 -7
- package/src/MastheadMenuItemTemplate.tsx +123 -0
- package/src/MastheadMenuTemplate.tsx +142 -0
- package/src/MastheadMobileMenu.ts +3 -3
- package/src/MastheadMobileMenuTemplate.tsx +274 -0
- package/src/MastheadProfileMenu.ts +10 -23
- package/src/MastheadProfileMenuTemplate.tsx +143 -0
- package/src/MastheadShell.ts +3 -5
- package/src/MastheadShellTemplate.tsx +228 -0
- package/src/SearchableListBase.ts +37 -1
- package/src/SearchableListBaseTemplate.tsx +38 -2
- package/src/SecondaryNavigation.ts +21 -6
- package/src/SelectBase.ts +8 -3
- package/src/Tab.ts +4 -24
- package/src/TabHeaderTemplate.tsx +153 -0
- package/src/TabInOverflowTemplate.tsx +68 -0
- package/src/TabNavigation.ts +61 -44
- package/src/TabNavigationPopoverTemplate.tsx +27 -0
- package/src/TabNavigationTemplate.tsx +98 -0
- package/src/TabTemplate.tsx +7 -0
- package/src/generated/i18n/i18n-defaults.ts +2 -2
- package/src/generated/themes/Button.css.ts +1 -1
- package/src/generated/themes/ListGroupHeader.css.ts +1 -1
- package/src/generated/themes/PromoTile.css.ts +1 -1
- package/src/generated/themes/TabInOverflow.css.ts +1 -1
- package/src/i18n/messagebundle.properties +4 -0
- package/src/i18n/messagebundle_en.properties +2 -0
- package/src/themes/Button.css +2 -1
- package/src/themes/ListGroupHeader.css +50 -7
- package/src/themes/PromoTile.css +1 -0
- package/src/themes/TabInOverflow.css +9 -4
- package/dist/assets/messagebundle_en-DBpf5Il2.js +0 -1
- package/dist/generated/templates/MastheadCountrySelectorTemplate.lit.d.ts +0 -3
- package/dist/generated/templates/MastheadCountrySelectorTemplate.lit.js +0 -13
- package/dist/generated/templates/MastheadCountrySelectorTemplate.lit.js.map +0 -1
- package/dist/generated/templates/MastheadItemTemplate.lit.d.ts +0 -3
- package/dist/generated/templates/MastheadItemTemplate.lit.js +0 -43
- package/dist/generated/templates/MastheadItemTemplate.lit.js.map +0 -1
- package/dist/generated/templates/MastheadMenuItemTemplate.lit.d.ts +0 -3
- package/dist/generated/templates/MastheadMenuItemTemplate.lit.js +0 -21
- package/dist/generated/templates/MastheadMenuItemTemplate.lit.js.map +0 -1
- package/dist/generated/templates/MastheadMenuTemplate.lit.d.ts +0 -3
- package/dist/generated/templates/MastheadMenuTemplate.lit.js +0 -25
- package/dist/generated/templates/MastheadMenuTemplate.lit.js.map +0 -1
- package/dist/generated/templates/MastheadMobileMenuTemplate.lit.d.ts +0 -3
- package/dist/generated/templates/MastheadMobileMenuTemplate.lit.js +0 -37
- package/dist/generated/templates/MastheadMobileMenuTemplate.lit.js.map +0 -1
- package/dist/generated/templates/MastheadProfileMenuTemplate.lit.d.ts +0 -3
- package/dist/generated/templates/MastheadProfileMenuTemplate.lit.js +0 -18
- package/dist/generated/templates/MastheadProfileMenuTemplate.lit.js.map +0 -1
- package/dist/generated/templates/MastheadShellTemplate.lit.d.ts +0 -3
- package/dist/generated/templates/MastheadShellTemplate.lit.js +0 -28
- package/dist/generated/templates/MastheadShellTemplate.lit.js.map +0 -1
- package/dist/generated/templates/TabHeaderTemplate.lit.d.ts +0 -3
- package/dist/generated/templates/TabHeaderTemplate.lit.js +0 -52
- package/dist/generated/templates/TabHeaderTemplate.lit.js.map +0 -1
- package/dist/generated/templates/TabInOverflowTemplate.lit.d.ts +0 -3
- package/dist/generated/templates/TabInOverflowTemplate.lit.js +0 -15
- package/dist/generated/templates/TabInOverflowTemplate.lit.js.map +0 -1
- package/dist/generated/templates/TabNavigationPopoverTemplate.lit.d.ts +0 -3
- package/dist/generated/templates/TabNavigationPopoverTemplate.lit.js +0 -8
- package/dist/generated/templates/TabNavigationPopoverTemplate.lit.js.map +0 -1
- package/dist/generated/templates/TabNavigationTemplate.lit.d.ts +0 -3
- package/dist/generated/templates/TabNavigationTemplate.lit.js +0 -16
- package/dist/generated/templates/TabNavigationTemplate.lit.js.map +0 -1
- package/dist/generated/templates/TabTemplate.lit.d.ts +0 -3
- package/dist/generated/templates/TabTemplate.lit.js +0 -7
- package/dist/generated/templates/TabTemplate.lit.js.map +0 -1
- package/src/MastheadCountrySelector.hbs +0 -76
- package/src/MastheadItem.hbs +0 -136
- package/src/MastheadMenu.hbs +0 -131
- package/src/MastheadMenuItem.hbs +0 -102
- package/src/MastheadMobileMenu.hbs +0 -253
- package/src/MastheadProfileMenu.hbs +0 -121
- package/src/MastheadShell.hbs +0 -223
- package/src/Tab.hbs +0 -1
- package/src/TabHeader.hbs +0 -141
- package/src/TabInOverflow.hbs +0 -59
- package/src/TabNavigation.hbs +0 -88
- package/src/TabNavigationPopover.hbs +0 -18
- package/src/generated/templates/MastheadCountrySelectorTemplate.lit.ts +0 -17
- package/src/generated/templates/MastheadItemTemplate.lit.ts +0 -47
- package/src/generated/templates/MastheadMenuItemTemplate.lit.ts +0 -25
- package/src/generated/templates/MastheadMenuTemplate.lit.ts +0 -29
- package/src/generated/templates/MastheadMobileMenuTemplate.lit.ts +0 -41
- package/src/generated/templates/MastheadProfileMenuTemplate.lit.ts +0 -22
- package/src/generated/templates/MastheadShellTemplate.lit.ts +0 -32
- package/src/generated/templates/TabHeaderTemplate.lit.ts +0 -56
- package/src/generated/templates/TabInOverflowTemplate.lit.ts +0 -19
- package/src/generated/templates/TabNavigationPopoverTemplate.lit.ts +0 -12
- package/src/generated/templates/TabNavigationTemplate.lit.ts +0 -20
- package/src/generated/templates/TabTemplate.lit.ts +0 -11
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import type UDExMastheadShell from "./MastheadShell.js";
|
|
2
|
+
import UDExMastheadItem from "./MastheadItem.js";
|
|
3
|
+
import UDExControlButton from "./ControlButton.js";
|
|
4
|
+
import UDExButtonSize from "./types/ButtonSize.js";
|
|
5
|
+
import declineIcon from "@ui5/webcomponents-icons/dist/decline.js";
|
|
6
|
+
import searchIcon from "@ui5/webcomponents-icons/dist/search.js";
|
|
7
|
+
import menuIcon from "@ui5/webcomponents-icons/dist/menu2.js";
|
|
8
|
+
|
|
9
|
+
export default function MastheadShellTemplate(this: UDExMastheadShell) {
|
|
10
|
+
return (
|
|
11
|
+
<header
|
|
12
|
+
className={this.mainClass}
|
|
13
|
+
onKeyDown={this.handleKeyDown}>
|
|
14
|
+
<div className="udex-masthead-shell__main-content">
|
|
15
|
+
<div className="udex-masthead-shell__landing-wrap">
|
|
16
|
+
{this.logoUrl && logo.call(this)}
|
|
17
|
+
{this.siteLabel && siteLabel.call(this)}
|
|
18
|
+
{this.coBrandImage && coBrand.call(this)}
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
{this.isMainMenuVisible && (
|
|
22
|
+
<nav
|
|
23
|
+
className="udex-masthead-shell__nav"
|
|
24
|
+
aria-label={this.mainNavigationAriaLabel}>
|
|
25
|
+
<ul
|
|
26
|
+
className="udex-masthead-shell__main-menu"
|
|
27
|
+
aria-label={this.mainNavigationAriaLabel}>
|
|
28
|
+
{this.menuItems.map(item => (
|
|
29
|
+
<li
|
|
30
|
+
key={item._id}
|
|
31
|
+
className="udex-masthead-shell__item"
|
|
32
|
+
onui5-item-click={this.setSelectedItem}>
|
|
33
|
+
<slot name={item._individualSlot}></slot>
|
|
34
|
+
</li>
|
|
35
|
+
))}
|
|
36
|
+
</ul>
|
|
37
|
+
</nav>
|
|
38
|
+
)}
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
{this.isSearchVisible && (
|
|
42
|
+
<>
|
|
43
|
+
<div
|
|
44
|
+
className="udex-masthead-shell__search-container"
|
|
45
|
+
onui5-search-keydown={this.handleSearchKeyDown}>
|
|
46
|
+
<slot name="search"></slot>
|
|
47
|
+
</div>
|
|
48
|
+
{this._isSearchOpened && (
|
|
49
|
+
<div className="udex-masthead-shell__btn-holder">
|
|
50
|
+
<UDExControlButton
|
|
51
|
+
class="udex-masthead-shell__close-search-btn"
|
|
52
|
+
part="search-close-button"
|
|
53
|
+
size={UDExButtonSize.Small}
|
|
54
|
+
icon={declineIcon}
|
|
55
|
+
tooltip={this.closeButtonAccessibleName}
|
|
56
|
+
accessible-name={this.closeButtonAccessibleName}
|
|
57
|
+
onClick={this.handleCloseSearch as any}>
|
|
58
|
+
</UDExControlButton>
|
|
59
|
+
</div>
|
|
60
|
+
)}
|
|
61
|
+
</>
|
|
62
|
+
)}
|
|
63
|
+
|
|
64
|
+
<div className={this.rightMenuClass}>
|
|
65
|
+
{this.hasExploreSAP && (
|
|
66
|
+
<div
|
|
67
|
+
className="udex-masthead-shell__explore"
|
|
68
|
+
onui5-item-click={this.setSelectedItem}>
|
|
69
|
+
<slot name="exploreSAP"></slot>
|
|
70
|
+
</div>
|
|
71
|
+
)}
|
|
72
|
+
{this.hasSearch && (
|
|
73
|
+
<div className="udex-masthead-shell__search-icon udex-masthead-shell__item_icon">
|
|
74
|
+
<UDExMastheadItem
|
|
75
|
+
class="udex-masthead-shell__search-btn"
|
|
76
|
+
part="search-button"
|
|
77
|
+
icon={searchIcon}
|
|
78
|
+
onClick={this.handleSearchClick as any}
|
|
79
|
+
accessible-name={this.openSearchButtonAccessibleNameText}
|
|
80
|
+
icon-alt={this.openSearchButtonAccessibleNameText}>
|
|
81
|
+
</UDExMastheadItem>
|
|
82
|
+
</div>
|
|
83
|
+
)}
|
|
84
|
+
{this.hasJoule && (
|
|
85
|
+
<div
|
|
86
|
+
className="udex-masthead-shell__joule udex-masthead-shell__item_icon"
|
|
87
|
+
onui5-item-click={this.setSelectedItem}
|
|
88
|
+
onClick={this.handleJouleClick as any}>
|
|
89
|
+
<slot name="joule"></slot>
|
|
90
|
+
</div>
|
|
91
|
+
)}
|
|
92
|
+
{this.hasCart && (
|
|
93
|
+
<div
|
|
94
|
+
className="udex-masthead-shell__cart udex-masthead-shell__item_icon"
|
|
95
|
+
onui5-item-click={this.setSelectedItem}
|
|
96
|
+
onClick={this.handleCartClick as any}>
|
|
97
|
+
<slot name="cart"></slot>
|
|
98
|
+
</div>
|
|
99
|
+
)}
|
|
100
|
+
{this.hasSupport && (
|
|
101
|
+
<div
|
|
102
|
+
className="udex-masthead-shell__support udex-masthead-shell__item_icon"
|
|
103
|
+
onui5-item-click={this.setSelectedItem}
|
|
104
|
+
onClick={this.handleSupportClick as any}>
|
|
105
|
+
<slot name="support"></slot>
|
|
106
|
+
</div>
|
|
107
|
+
)}
|
|
108
|
+
{this.hasProfile && (
|
|
109
|
+
<div
|
|
110
|
+
className="udex-masthead-shell__profile udex-masthead-shell__item_icon"
|
|
111
|
+
onui5-item-click={this.setSelectedItem}
|
|
112
|
+
onclick-default={this.handleProfileClick}>
|
|
113
|
+
<slot name="profile"></slot>
|
|
114
|
+
</div>
|
|
115
|
+
)}
|
|
116
|
+
{this.hasCountrySelector && (
|
|
117
|
+
<div
|
|
118
|
+
className="udex-masthead-shell__country-selector udex-masthead-shell__item_icon"
|
|
119
|
+
onui5-item-click={this.setSelectedItem}
|
|
120
|
+
onClick={this.handleCountrySelectorClick as any}>
|
|
121
|
+
<slot name="countrySelector"></slot>
|
|
122
|
+
</div>
|
|
123
|
+
)}
|
|
124
|
+
{this.hasMobileMenuButtons && (
|
|
125
|
+
<>
|
|
126
|
+
<UDExMastheadItem
|
|
127
|
+
class="udex-masthead-shell__menu-btn"
|
|
128
|
+
accessible-role="button"
|
|
129
|
+
part="menu-open-btn"
|
|
130
|
+
accessible-name="menu"
|
|
131
|
+
icon={menuIcon}
|
|
132
|
+
onui5-item-click={this.handleOpenMobileMenu}
|
|
133
|
+
{...{ "_is-menu-open-btn": "" }}>
|
|
134
|
+
<slot slot="dropdown" name="mobileMenu"></slot>
|
|
135
|
+
</UDExMastheadItem>
|
|
136
|
+
<UDExMastheadItem
|
|
137
|
+
class="udex-masthead-shell__close-btn"
|
|
138
|
+
accessible-role="button"
|
|
139
|
+
part="menu-close-btn"
|
|
140
|
+
onKeyDown={this.handleEnterAndSpaceOnCloseBtn}
|
|
141
|
+
onui5-item-click={this.closeMobileMenu}
|
|
142
|
+
icon={declineIcon}
|
|
143
|
+
accessible-name={this.mobileCloseButtonAccessibleName}
|
|
144
|
+
hide-active-border
|
|
145
|
+
{...{ "_is-menu-close-btn": "" }}>
|
|
146
|
+
</UDExMastheadItem>
|
|
147
|
+
</>
|
|
148
|
+
)}
|
|
149
|
+
</div>
|
|
150
|
+
</header>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function logo(this: UDExMastheadShell) {
|
|
155
|
+
return this.homeUrl ? (
|
|
156
|
+
<a
|
|
157
|
+
className="udex-masthead-shell__logo udex-masthead-shell__logo--link"
|
|
158
|
+
target="_self"
|
|
159
|
+
role="link"
|
|
160
|
+
tabindex={0}
|
|
161
|
+
onClick={this.handleLogoClick as any}
|
|
162
|
+
href={this.homeUrl}
|
|
163
|
+
title={this.logoTitle}
|
|
164
|
+
aria-label={this.homepageAriaLabel}>
|
|
165
|
+
<img
|
|
166
|
+
className="udex-masthead-shell__logo-image"
|
|
167
|
+
src={this.logoUrl}
|
|
168
|
+
alt={this.logoAlt}
|
|
169
|
+
/>
|
|
170
|
+
</a>
|
|
171
|
+
) : (
|
|
172
|
+
<div className="udex-masthead-shell__logo">
|
|
173
|
+
<img
|
|
174
|
+
className="udex-masthead-shell__logo-image"
|
|
175
|
+
src={this.logoUrl}
|
|
176
|
+
alt={this.logoAlt}
|
|
177
|
+
/>
|
|
178
|
+
</div>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function siteLabel(this: UDExMastheadShell) {
|
|
183
|
+
return this.siteLabelUrl ? (
|
|
184
|
+
<a
|
|
185
|
+
className="udex-masthead-shell__site-label udex-masthead-shell__site-label--link"
|
|
186
|
+
role="link"
|
|
187
|
+
target="_self"
|
|
188
|
+
onClick={this.handleSiteLabelClick as any}
|
|
189
|
+
href={this.siteLabelUrl}
|
|
190
|
+
tabindex={0}
|
|
191
|
+
title={this.siteLabelTitle}
|
|
192
|
+
aria-label={this.siteLabelAriaLabel}>
|
|
193
|
+
{this.siteLabel}
|
|
194
|
+
</a>
|
|
195
|
+
) : (
|
|
196
|
+
<div className="udex-masthead-shell__site-label">{this.siteLabel}</div>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function coBrand(this: UDExMastheadShell) {
|
|
201
|
+
return this.coBrandUrl ? (
|
|
202
|
+
<div className="udex-masthead-shell__co-brand">
|
|
203
|
+
<a
|
|
204
|
+
className="udex-masthead-shell__co-brand-link"
|
|
205
|
+
target="_self"
|
|
206
|
+
role="link"
|
|
207
|
+
onClick={this.handleCoBrandClick as any}
|
|
208
|
+
href={this.coBrandUrl}
|
|
209
|
+
tabindex={0}
|
|
210
|
+
title={this.coBrandTitle}
|
|
211
|
+
aria-label={this.coBrandAriaLabel}>
|
|
212
|
+
<img
|
|
213
|
+
className="udex-masthead-shell__co-brand-image"
|
|
214
|
+
src={this.coBrandImage}
|
|
215
|
+
alt={this.coBrandAlt}
|
|
216
|
+
/>
|
|
217
|
+
</a>
|
|
218
|
+
</div>
|
|
219
|
+
) : (
|
|
220
|
+
<div className="udex-masthead-shell__co-brand">
|
|
221
|
+
<img
|
|
222
|
+
className="udex-masthead-shell__co-brand-image"
|
|
223
|
+
src={this.coBrandImage}
|
|
224
|
+
alt={this.coBrandAlt}
|
|
225
|
+
/>
|
|
226
|
+
</div>
|
|
227
|
+
);
|
|
228
|
+
}
|
|
@@ -17,7 +17,9 @@ import type UDExListItem from "./ListItem.js";
|
|
|
17
17
|
import type UDExFilterMenuItem from "./FilterMenuItem.js";
|
|
18
18
|
import type UDExSelectBoxItem from "./SelectBoxItem.js";
|
|
19
19
|
import { SHOW_SEARCH_AFTER_COUNT, UDExPopoverPart } from "./types/SearchableListBase.js";
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
NO_MATCHES_FOUND, RESULT_RETURNED, STARS,
|
|
22
|
+
} from "./generated/i18n/i18n-defaults.js";
|
|
21
23
|
import translate from "./utils/translate.js";
|
|
22
24
|
|
|
23
25
|
export type UDExItemFromList = UDExListItemBase | UDExListGroupHeaderBase | null | undefined;
|
|
@@ -351,6 +353,17 @@ class UDExSearchableListBase extends UI5Element {
|
|
|
351
353
|
if (!originalItem) { return; }
|
|
352
354
|
originalItem.collapsed = e.detail.collapsed;
|
|
353
355
|
originalItem.setCollapsedItems?.();
|
|
356
|
+
// NOTE: no dynamic screen-reader announcement of the new expanded/collapsed state
|
|
357
|
+
// is emitted here. JAWS announces it natively — the list uses role="tree" (see
|
|
358
|
+
// List._hasCollapsibleGroups) so JAWS enters application mode and reads the focused
|
|
359
|
+
// header's aria-expanded on every arrow toggle. VoiceOver, however, refuses to
|
|
360
|
+
// re-announce aria-expanded on a treeitem whose children role="group" is a sibling
|
|
361
|
+
// rather than a DOM descendant (unavoidable across the shadow boundary; aria-owns
|
|
362
|
+
// can't bridge the nested shadow roots in multi-select). Every aria-live approach
|
|
363
|
+
// (a shadow-local span, UI5's top-level InvisibleMessage) is dropped by VoiceOver
|
|
364
|
+
// inside this teleported popover, and a same-element focus re-read is suppressed by
|
|
365
|
+
// VoiceOver. VoiceOver still reads the full state when focus first lands on the
|
|
366
|
+
// header. This is a documented VoiceOver-specific limitation.
|
|
354
367
|
}
|
|
355
368
|
|
|
356
369
|
onSelectAllHeaderPress(e:CustomEvent) {
|
|
@@ -847,9 +860,32 @@ class UDExSearchableListBase extends UI5Element {
|
|
|
847
860
|
if (this.isTreeStructure) {
|
|
848
861
|
return "tree";
|
|
849
862
|
}
|
|
863
|
+
if (this.isPerGroupListbox) {
|
|
864
|
+
// Each group is its own role="listbox" (see ListGroupHeaderTemplate); the outer
|
|
865
|
+
// container must be transparent, otherwise the per-group listboxes would be nested
|
|
866
|
+
// inside a listbox (invalid, and JAWS would fall back to one flat count).
|
|
867
|
+
return "presentation";
|
|
868
|
+
}
|
|
850
869
|
return this.defaultAccessibleRole;
|
|
851
870
|
}
|
|
852
871
|
|
|
872
|
+
/**
|
|
873
|
+
* FilterMenu real-focus SingleSelect where EVERY top-level item is a group.
|
|
874
|
+
* Renders each group as its own role="listbox" so JAWS counts options natively
|
|
875
|
+
* per group ("1 of 4"): JAWS ignores role="group" boundaries and author
|
|
876
|
+
* aria-posinset within a single listbox, but counts reliably within a flat
|
|
877
|
+
* listbox. Not engaged for aria-activedescendant widgets (SelectBox), trees,
|
|
878
|
+
* MultiSelect/RadioGroup, or mixed grouped+ungrouped lists (ungrouped options
|
|
879
|
+
* would be orphaned once the outer listbox role is dropped).
|
|
880
|
+
*/
|
|
881
|
+
get isPerGroupListbox(): boolean {
|
|
882
|
+
if (this.isTreeStructure || this._activeDescendantMode || !this.modeSingleSelect) {
|
|
883
|
+
return false;
|
|
884
|
+
}
|
|
885
|
+
const items = this.items;
|
|
886
|
+
return items.length > 0 && items.every(item => item.isGroup);
|
|
887
|
+
}
|
|
888
|
+
|
|
853
889
|
get listItemRole(): string {
|
|
854
890
|
if (this.isTreeStructure) {
|
|
855
891
|
return "treeitem";
|
|
@@ -100,8 +100,26 @@ function renderGroupHeader(this: UDExSearchableListBase, processedItem: UDExProc
|
|
|
100
100
|
const { item, groupItems } = processedItem;
|
|
101
101
|
const header = item as UDExListGroupHeaderBase;
|
|
102
102
|
const childAccessibleRole = this.isTreeStructure ? "treeitem" : undefined;
|
|
103
|
+
// Position among sibling group headers, for the explicit tree-position attributes below.
|
|
104
|
+
const treeGroups = this.isTreeStructure ? this._filteredItems.filter(p => p.isGroup) : [];
|
|
105
|
+
const groupPosInSet = treeGroups.indexOf(processedItem) + 1;
|
|
106
|
+
const groupSetSize = treeGroups.length;
|
|
107
|
+
// Explicit per-group tree position for the FilterMenu (real-focus) treeitems. Scoped to
|
|
108
|
+
// MultiSelect only: the SingleSelect tree is now conformantly nested (role="group" inside
|
|
109
|
+
// the parent treeitem) so JAWS/NVDA count children natively — explicit values there just
|
|
110
|
+
// confuse JAWS. MultiSelect still uses the malformed sibling structure until Phase 2, so it
|
|
111
|
+
// keeps the explicit override. Not applied in aria-activedescendant mode (SelectBox announces
|
|
112
|
+
// position via its own live region — see [[project_selectbox_aria_live_region]]).
|
|
113
|
+
const treePositionAttrs = (!this._activeDescendantMode && this.isTreeStructure && this.modeMultiSelect) ? {
|
|
114
|
+
"_aria-pos-in-set": groupPosInSet,
|
|
115
|
+
"_aria-set-size": groupSetSize,
|
|
116
|
+
} : {};
|
|
103
117
|
// In aria-activedescendant mode (SelectBox), each group header host element
|
|
104
118
|
// must carry role + ARIA state so screen readers can reach them via the pointer.
|
|
119
|
+
// In real-focus mode (FilterMenu) the host is always transparent (role="none"):
|
|
120
|
+
// the shadow DOM's div.udex-list__group provides the single role="group" with
|
|
121
|
+
// aria-labelledby="group-heading" in non-tree mode; in tree mode the treeitem is
|
|
122
|
+
// on the focusable div inside the shadow.
|
|
105
123
|
const hostAriaAttrs = this._activeDescendantMode ? {
|
|
106
124
|
role: (this.isTreeStructure ? "treeitem" : "option") as AriaRole,
|
|
107
125
|
"aria-label": cleanLabel(item.label ?? ""),
|
|
@@ -110,13 +128,15 @@ function renderGroupHeader(this: UDExSearchableListBase, processedItem: UDExProc
|
|
|
110
128
|
"aria-disabled": item.disabled ? "true" as string : undefined,
|
|
111
129
|
"aria-expanded": header.collapsible ? (header.expanded ? "true" as string : "false" as string) : undefined,
|
|
112
130
|
"_use-host-aria-role": true,
|
|
113
|
-
} : { role:
|
|
131
|
+
} : { role: "none" as AriaRole };
|
|
114
132
|
return (
|
|
115
133
|
<UDExListGroupHeader
|
|
116
134
|
key={index}
|
|
117
135
|
id={item._id}
|
|
118
136
|
{...hostAriaAttrs}
|
|
137
|
+
{...treePositionAttrs}
|
|
119
138
|
_tree-mode={this.isTreeStructure || undefined}
|
|
139
|
+
_group-as-listbox={this.isPerGroupListbox || undefined}
|
|
120
140
|
{...(index === 0 ? { "_no-border": "" } : {})}
|
|
121
141
|
_additional-class-name="udex-searchable-list__header"
|
|
122
142
|
class={this.groupClassName}
|
|
@@ -135,7 +155,7 @@ function renderGroupHeader(this: UDExSearchableListBase, processedItem: UDExProc
|
|
|
135
155
|
onAccordionIconClick={this.handleAccordionIconClick}
|
|
136
156
|
indeterminate={header.indeterminate}>
|
|
137
157
|
{groupItems.map((child, i) =>
|
|
138
|
-
renderListItem(child as UDExListItem, i, "none", childAccessibleRole, this.fireFirstIconClickEvent, this.fireSecondIconClickEvent, this._activeDescendantMode, this.isTreeStructure, this.modeMultiSelect)
|
|
158
|
+
renderListItem(child as UDExListItem, i, "none", childAccessibleRole, this.fireFirstIconClickEvent, this.fireSecondIconClickEvent, this._activeDescendantMode, this.isTreeStructure, this.modeMultiSelect, i + 1, groupItems.length)
|
|
139
159
|
)}
|
|
140
160
|
</UDExListGroupHeader>
|
|
141
161
|
);
|
|
@@ -151,6 +171,8 @@ function renderListItem(
|
|
|
151
171
|
activeDescendantMode?: boolean,
|
|
152
172
|
isTreeStructure?: boolean,
|
|
153
173
|
modeMultiSelect?: boolean,
|
|
174
|
+
posInSet?: number,
|
|
175
|
+
setSize?: number,
|
|
154
176
|
) {
|
|
155
177
|
// In aria-activedescendant mode (SelectBox), role + ARIA state must be on the
|
|
156
178
|
// host element so screen readers can reach them via the aria-activedescendant pointer.
|
|
@@ -167,6 +189,19 @@ function renderListItem(
|
|
|
167
189
|
} : {
|
|
168
190
|
...(accessibleRole ? { "accessible-role": accessibleRole } : {}),
|
|
169
191
|
};
|
|
192
|
+
// Explicit per-group position for FilterMenu real-focus items. Applied whenever
|
|
193
|
+
// posInSet/setSize are provided (i.e. items inside a group header), across all
|
|
194
|
+
// modes except aria-activedescendant (SelectBox uses its own live region):
|
|
195
|
+
// • Non-tree grouped listbox (SingleSelect non-collapsible): options get per-group
|
|
196
|
+
// counts since native shadow-DOM counting is unreliable for nested custom elements.
|
|
197
|
+
// • SingleSelect conformant-nested tree: explicit values match the native structural
|
|
198
|
+
// count, so JAWS trusts and re-announces on every arrow step (not just group entry).
|
|
199
|
+
// • MultiSelect sibling tree (Phase 2 pending): keeps the fix-20 override.
|
|
200
|
+
// Not applied in aria-activedescendant mode (SelectBox — see [[project_selectbox_aria_live_region]]).
|
|
201
|
+
const treePositionAttrs = (!activeDescendantMode && posInSet != null && setSize != null) ? {
|
|
202
|
+
"_aria-pos-in-set": posInSet,
|
|
203
|
+
"_aria-set-size": setSize,
|
|
204
|
+
} : {};
|
|
170
205
|
return (
|
|
171
206
|
<UDExListItem
|
|
172
207
|
key={index}
|
|
@@ -198,6 +233,7 @@ function renderListItem(
|
|
|
198
233
|
size={item.size}
|
|
199
234
|
type={item.type}
|
|
200
235
|
{...hostAriaAttrs}
|
|
236
|
+
{...treePositionAttrs}
|
|
201
237
|
{...((item as any).innerHTML ? { dangerouslySetInnerHTML: { __html: (item as any).innerHTML } } : {})}>
|
|
202
238
|
</UDExListItem>
|
|
203
239
|
);
|
|
@@ -25,8 +25,9 @@ import translate from "./utils/translate.js";
|
|
|
25
25
|
// Styles
|
|
26
26
|
import SecondaryNavigationCss from "./generated/themes/SecondaryNavigation.css.js";
|
|
27
27
|
|
|
28
|
-
const canvasContentFont: string = "
|
|
28
|
+
const canvasContentFont: string = "14px '72 Brand Variable'";
|
|
29
29
|
const rootClass = "udex-secondary-navigation__root";
|
|
30
|
+
const ITEM_ICON_WIDTH = 20;
|
|
30
31
|
|
|
31
32
|
type UDExSecondaryNavigationClickEventDetail = {
|
|
32
33
|
originalEvent: Event,
|
|
@@ -268,7 +269,10 @@ class UDExSecondaryNavigation extends UI5Element {
|
|
|
268
269
|
}
|
|
269
270
|
|
|
270
271
|
reflowItems(): void {
|
|
271
|
-
const
|
|
272
|
+
const headingWidth = this.headingHolder
|
|
273
|
+
? this.headingHolder.offsetWidth + (parseFloat(getComputedStyle(this.headingHolder).marginInlineEnd) || 0)
|
|
274
|
+
: 0;
|
|
275
|
+
const availableWidth = this.rootHolder.offsetWidth - headingWidth - (this.optionalButtons?.offsetWidth || 0);
|
|
272
276
|
const moreButtonWidth = this.getMoreButtonWidth();
|
|
273
277
|
const itemsGap = 20;
|
|
274
278
|
const widths = this.parsedItems.map(item => this.getItemWidth(item));
|
|
@@ -306,16 +310,27 @@ class UDExSecondaryNavigation extends UI5Element {
|
|
|
306
310
|
|
|
307
311
|
getItemWidth(item: NavItem): number {
|
|
308
312
|
const context = this.getCanvasContext();
|
|
309
|
-
context.font =
|
|
313
|
+
context.font = this.getCanvasFont();
|
|
314
|
+
const iconWidth = item.items?.length ? ITEM_ICON_WIDTH : 0;
|
|
310
315
|
|
|
311
|
-
return Math.ceil(context.measureText(item.title).width);
|
|
316
|
+
return Math.ceil(context.measureText(item.title).width) + iconWidth;
|
|
312
317
|
}
|
|
313
318
|
|
|
314
319
|
getMoreButtonWidth(): number {
|
|
315
320
|
const context = this.getCanvasContext();
|
|
316
|
-
context.font =
|
|
321
|
+
context.font = this.getCanvasFont();
|
|
317
322
|
|
|
318
|
-
return Math.ceil(context.measureText(this.moreButtonText).width);
|
|
323
|
+
return Math.ceil(context.measureText(this.moreButtonText).width) + ITEM_ICON_WIDTH;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
getCanvasFont(): string {
|
|
327
|
+
const navItem = this.domNavItems[0];
|
|
328
|
+
const btn = navItem?.shadowRoot?.querySelector<HTMLElement>(".udex-secondary-navigation__item");
|
|
329
|
+
if (btn) {
|
|
330
|
+
const cs = getComputedStyle(btn);
|
|
331
|
+
return `${cs.fontWeight} ${cs.fontSize} ${cs.fontFamily}`;
|
|
332
|
+
}
|
|
333
|
+
return canvasContentFont;
|
|
319
334
|
}
|
|
320
335
|
|
|
321
336
|
getCanvasContext(): CanvasRenderingContext2D {
|
package/src/SelectBase.ts
CHANGED
|
@@ -14,7 +14,7 @@ import type UDExSearch from "./Search.js";
|
|
|
14
14
|
import "@ui5/webcomponents-icons/dist/decline.js";
|
|
15
15
|
import "@ui5/webcomponents-icons/dist/navigation-down-arrow.js";
|
|
16
16
|
import {
|
|
17
|
-
COUNTRY_SELECT, STARS, SELECTED, UNSELECTED, INDETERMINATE, DISABLED,
|
|
17
|
+
COUNTRY_SELECT, STARS, SELECTED, UNSELECTED, INDETERMINATE, DISABLED, EXPANDED, COLLAPSED,
|
|
18
18
|
} from "./generated/i18n/i18n-defaults.js";
|
|
19
19
|
import SearchableListBaseTemplate from "./SearchableListBaseTemplate.js";
|
|
20
20
|
import CountrySelectorTemplate from "./CountrySelectorTemplate.js";
|
|
@@ -697,6 +697,12 @@ class UDExSelectBase extends UDExSearchableListBase {
|
|
|
697
697
|
e.preventDefault();
|
|
698
698
|
const activeItem = this._activeDescendantItem;
|
|
699
699
|
if (activeItem.isGroup) {
|
|
700
|
+
// Group-header selection is "select all" — only meaningful in MultiSelect.
|
|
701
|
+
// In SingleSelect (and RadioGroup) a group header is not a selectable option,
|
|
702
|
+
// so Enter/Space must do nothing (collapse/expand stays on Left/Right + chevron).
|
|
703
|
+
if (!this.modeMultiSelect) {
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
700
706
|
// Group header: fire header-press (same event the click handler fires) so
|
|
701
707
|
// handleHeaderPress → onHeaderPress → handleGroupHeaderSelection runs.
|
|
702
708
|
activeItem.fireDecoratorEvent("header-press", { item: activeItem });
|
|
@@ -1138,8 +1144,7 @@ class UDExSelectBase extends UDExSearchableListBase {
|
|
|
1138
1144
|
const parts: string[] = [];
|
|
1139
1145
|
|
|
1140
1146
|
if (item.collapsible) {
|
|
1141
|
-
|
|
1142
|
-
parts.push(item.expanded ? "expanded" : "collapsed");
|
|
1147
|
+
parts.push(translate(UDExSearchableListBase, item.expanded ? EXPANDED : COLLAPSED));
|
|
1143
1148
|
}
|
|
1144
1149
|
|
|
1145
1150
|
if (item.disabled) {
|
package/src/Tab.ts
CHANGED
|
@@ -3,21 +3,18 @@ import type { DefaultSlot, Slot } from "@ui5/webcomponents-base/dist/UI5Element.
|
|
|
3
3
|
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
|
|
4
4
|
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
|
|
5
5
|
import slot from "@ui5/webcomponents-base/dist/decorators/slot-strict.js";
|
|
6
|
-
import
|
|
7
|
-
import executeTemplate from "@ui5/webcomponents-base/dist/renderer/executeTemplate.js";
|
|
6
|
+
import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js";
|
|
8
7
|
import TabNavigation from "./TabNavigation.js";
|
|
9
8
|
import UDExBadge from "./Badge.js";
|
|
10
9
|
import { UDExTarget } from "./types/common.js";
|
|
11
|
-
import TabTemplate from "./
|
|
12
|
-
import TabHeaderTemplate from "./generated/templates/TabHeaderTemplate.lit.js";
|
|
13
|
-
import TabInOverflowTemplate from "./generated/templates/TabInOverflowTemplate.lit.js";
|
|
10
|
+
import TabTemplate from "./TabTemplate.js";
|
|
14
11
|
import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js";
|
|
15
12
|
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
|
|
16
13
|
import { ATTENTION_BADGE } from "./generated/i18n/i18n-defaults.js";
|
|
14
|
+
import translate from "./utils/translate.js";
|
|
17
15
|
|
|
18
16
|
// Styles
|
|
19
17
|
import TabInOverflowCss from "./generated/themes/TabInOverflow.css.js";
|
|
20
|
-
import translate from "./utils/translate.js";
|
|
21
18
|
|
|
22
19
|
export interface ITab extends UI5Element {
|
|
23
20
|
getTabInHeaderDomRef: () => ITab | null;
|
|
@@ -40,7 +37,6 @@ export interface ITab extends UI5Element {
|
|
|
40
37
|
hasNotHref: boolean;
|
|
41
38
|
hasLinkSlot: boolean;
|
|
42
39
|
selectedClass: string;
|
|
43
|
-
tabNavigation: any;
|
|
44
40
|
_individualSlot: string;
|
|
45
41
|
_effectiveSlotName: string;
|
|
46
42
|
_slotName: string;
|
|
@@ -79,7 +75,7 @@ export interface ITab extends UI5Element {
|
|
|
79
75
|
*/
|
|
80
76
|
@customElement({
|
|
81
77
|
tag: "udex-tab",
|
|
82
|
-
renderer:
|
|
78
|
+
renderer: jsxRenderer,
|
|
83
79
|
template: TabTemplate,
|
|
84
80
|
dependencies: [UDExBadge],
|
|
85
81
|
})
|
|
@@ -409,22 +405,6 @@ class UDExTab extends UI5Element implements ITab {
|
|
|
409
405
|
}
|
|
410
406
|
return "";
|
|
411
407
|
}
|
|
412
|
-
|
|
413
|
-
get tabNavigation() {
|
|
414
|
-
return executeTemplate(UDExTab.headerTemplate, this);
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
get tabInOverflow() {
|
|
418
|
-
return executeTemplate(UDExTab.overflowTemplate, this);
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
static get headerTemplate() {
|
|
422
|
-
return TabHeaderTemplate;
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
static get overflowTemplate() {
|
|
426
|
-
return TabInOverflowTemplate;
|
|
427
|
-
}
|
|
428
408
|
}
|
|
429
409
|
|
|
430
410
|
UDExTab.define();
|