@sapudex/web-components 0.176.0 → 0.184.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.
Files changed (209) hide show
  1. package/bundle.esm.js +1 -1
  2. package/dist/Accordion.js +2 -1
  3. package/dist/Accordion.js.map +1 -1
  4. package/dist/AccordionItem.d.ts +0 -1
  5. package/dist/AccordionItem.js +2 -2
  6. package/dist/AccordionItem.js.map +1 -1
  7. package/dist/Badge.js +2 -1
  8. package/dist/Badge.js.map +1 -1
  9. package/dist/Breadcrumbs.d.ts +7 -7
  10. package/dist/Breadcrumbs.js +3 -3
  11. package/dist/Breadcrumbs.js.map +1 -1
  12. package/dist/CountrySelector.js +5 -5
  13. package/dist/CountrySelector.js.map +1 -1
  14. package/dist/DatePicker.d.ts +53 -26
  15. package/dist/DatePicker.js +205 -39
  16. package/dist/DatePicker.js.map +1 -1
  17. package/dist/FilterMenu.d.ts +4 -6
  18. package/dist/FilterMenu.js +10 -10
  19. package/dist/FilterMenu.js.map +1 -1
  20. package/dist/Footer.js +6 -2
  21. package/dist/Footer.js.map +1 -1
  22. package/dist/HeroBanner.d.ts +0 -1
  23. package/dist/HeroBanner.js +2 -1
  24. package/dist/HeroBanner.js.map +1 -1
  25. package/dist/Link.js +2 -0
  26. package/dist/Link.js.map +1 -1
  27. package/dist/ListSelectAll.js +2 -0
  28. package/dist/ListSelectAll.js.map +1 -1
  29. package/dist/MastheadItem.js +2 -2
  30. package/dist/MastheadItem.js.map +1 -1
  31. package/dist/MastheadMenu.js +1 -1
  32. package/dist/MastheadMenu.js.map +1 -1
  33. package/dist/MastheadMobileMenu.js +1 -1
  34. package/dist/MastheadMobileMenu.js.map +1 -1
  35. package/dist/MastheadShell.d.ts +1 -0
  36. package/dist/MastheadShell.js +20 -1
  37. package/dist/MastheadShell.js.map +1 -1
  38. package/dist/MediaPlayer.js +2 -2
  39. package/dist/MediaPlayer.js.map +1 -1
  40. package/dist/MessageStrip.js +2 -1
  41. package/dist/MessageStrip.js.map +1 -1
  42. package/dist/RadioButton.js +0 -1
  43. package/dist/RadioButton.js.map +1 -1
  44. package/dist/Search.js +0 -1
  45. package/dist/Search.js.map +1 -1
  46. package/dist/SearchableListBase.js +3 -3
  47. package/dist/SearchableListBase.js.map +1 -1
  48. package/dist/SecondaryNavigation.js +1 -1
  49. package/dist/SecondaryNavigation.js.map +1 -1
  50. package/dist/SecondaryNavigationItem.js +1 -1
  51. package/dist/SecondaryNavigationItem.js.map +1 -1
  52. package/dist/SelectBox.d.ts +3 -3
  53. package/dist/SelectBox.js +6 -6
  54. package/dist/SelectBox.js.map +1 -1
  55. package/dist/SideNavigationMobile.js +1 -1
  56. package/dist/SideNavigationMobile.js.map +1 -1
  57. package/dist/StepInput.js +1 -1
  58. package/dist/StepInput.js.map +1 -1
  59. package/dist/TabNavigation.d.ts +4 -5
  60. package/dist/TabNavigation.js +16 -14
  61. package/dist/TabNavigation.js.map +1 -1
  62. package/dist/Table.js +2 -2
  63. package/dist/Table.js.map +1 -1
  64. package/dist/assets/{css_variables-a92ef9ad.css → bundle-c5e3cbf2.css} +1 -1
  65. package/dist/assets/{bundle.esm-f0e73f3b.js → bundle.esm-d98e72b5.js} +185 -185
  66. package/dist/css/themes/AccordionItem.css +1 -1
  67. package/dist/css/themes/Button.css +1 -1
  68. package/dist/css/themes/CountrySelector.css +1 -1
  69. package/dist/css/themes/ListItem.css +1 -1
  70. package/dist/css/themes/MastheadMenu.css +1 -1
  71. package/dist/css/themes/MastheadMobileMenu.css +1 -1
  72. package/dist/css/themes/MastheadProfileMenu.css +1 -1
  73. package/dist/css/themes/MessageStrip.css +1 -1
  74. package/dist/css/themes/PhoneNumberField.css +1 -1
  75. package/dist/css/themes/RatingIndicator.css +1 -1
  76. package/dist/css/themes/Review.css +1 -1
  77. package/dist/css/themes/ReviewItem.css +1 -1
  78. package/dist/css/themes/Search.css +1 -1
  79. package/dist/css/themes/SegmentedButton.css +1 -1
  80. package/dist/css/themes/SideNavigationMobileDropdown.css +1 -1
  81. package/dist/css/themes/Slider.css +1 -1
  82. package/dist/css/themes/StepInput.css +1 -1
  83. package/dist/css/themes/TabNavigation.css +1 -1
  84. package/dist/css/themes/Table.css +1 -1
  85. package/dist/custom-elements-internal.json +118 -100
  86. package/dist/custom-elements.json +113 -97
  87. package/dist/features/SearchSuggestionsPopover.d.ts +1 -1
  88. package/dist/generated/templates/BreadcrumbsPopoverTemplate.lit.js +1 -1
  89. package/dist/generated/templates/BreadcrumbsPopoverTemplate.lit.js.map +1 -1
  90. package/dist/generated/templates/DatePickerPopoverTemplate.lit.js +1 -1
  91. package/dist/generated/templates/DatePickerPopoverTemplate.lit.js.map +1 -1
  92. package/dist/generated/templates/DatePickerTemplate.lit.js +1 -1
  93. package/dist/generated/templates/DatePickerTemplate.lit.js.map +1 -1
  94. package/dist/generated/templates/FilterMenuTemplate.lit.js +2 -2
  95. package/dist/generated/templates/FilterMenuTemplate.lit.js.map +1 -1
  96. package/dist/generated/themes/AccordionItem.css.js +1 -1
  97. package/dist/generated/themes/AccordionItem.css.js.map +1 -1
  98. package/dist/generated/themes/Button.css.js +1 -1
  99. package/dist/generated/themes/Button.css.js.map +1 -1
  100. package/dist/generated/themes/CountrySelector.css.js +1 -1
  101. package/dist/generated/themes/CountrySelector.css.js.map +1 -1
  102. package/dist/generated/themes/ListItem.css.js +1 -1
  103. package/dist/generated/themes/ListItem.css.js.map +1 -1
  104. package/dist/generated/themes/MastheadMenu.css.js +1 -1
  105. package/dist/generated/themes/MastheadMenu.css.js.map +1 -1
  106. package/dist/generated/themes/MastheadMobileMenu.css.js +1 -1
  107. package/dist/generated/themes/MastheadMobileMenu.css.js.map +1 -1
  108. package/dist/generated/themes/MastheadProfileMenu.css.js +1 -1
  109. package/dist/generated/themes/MastheadProfileMenu.css.js.map +1 -1
  110. package/dist/generated/themes/MessageStrip.css.js +1 -1
  111. package/dist/generated/themes/MessageStrip.css.js.map +1 -1
  112. package/dist/generated/themes/PhoneNumberField.css.js +1 -1
  113. package/dist/generated/themes/PhoneNumberField.css.js.map +1 -1
  114. package/dist/generated/themes/RatingIndicator.css.js +1 -1
  115. package/dist/generated/themes/RatingIndicator.css.js.map +1 -1
  116. package/dist/generated/themes/Review.css.js +1 -1
  117. package/dist/generated/themes/Review.css.js.map +1 -1
  118. package/dist/generated/themes/ReviewItem.css.js +1 -1
  119. package/dist/generated/themes/ReviewItem.css.js.map +1 -1
  120. package/dist/generated/themes/Search.css.js +1 -1
  121. package/dist/generated/themes/Search.css.js.map +1 -1
  122. package/dist/generated/themes/SegmentedButton.css.js +1 -1
  123. package/dist/generated/themes/SegmentedButton.css.js.map +1 -1
  124. package/dist/generated/themes/SideNavigationMobileDropdown.css.js +1 -1
  125. package/dist/generated/themes/SideNavigationMobileDropdown.css.js.map +1 -1
  126. package/dist/generated/themes/Slider.css.js +1 -1
  127. package/dist/generated/themes/Slider.css.js.map +1 -1
  128. package/dist/generated/themes/StepInput.css.js +1 -1
  129. package/dist/generated/themes/StepInput.css.js.map +1 -1
  130. package/dist/generated/themes/TabNavigation.css.js +1 -1
  131. package/dist/generated/themes/TabNavigation.css.js.map +1 -1
  132. package/dist/generated/themes/Table.css.js +1 -1
  133. package/dist/generated/themes/Table.css.js.map +1 -1
  134. package/dist/vscode.html-custom-data.json +2 -12
  135. package/dist/web-types.json +19 -23
  136. package/package.json +2 -2
  137. package/src/Accordion.ts +2 -1
  138. package/src/AccordionItem.ts +2 -2
  139. package/src/Badge.ts +2 -1
  140. package/src/Breadcrumbs.hbs +3 -3
  141. package/src/Breadcrumbs.ts +14 -14
  142. package/src/BreadcrumbsPopover.hbs +1 -1
  143. package/src/CountrySelector.ts +5 -5
  144. package/src/DatePicker.hbs +4 -5
  145. package/src/DatePicker.ts +257 -64
  146. package/src/DatePickerPopover.hbs +2 -2
  147. package/src/FilterMenu.hbs +2 -1
  148. package/src/FilterMenu.ts +13 -14
  149. package/src/Footer.ts +6 -2
  150. package/src/HeroBanner.ts +2 -1
  151. package/src/Link.ts +2 -0
  152. package/src/ListSelectAll.ts +2 -0
  153. package/src/MastheadItem.ts +2 -2
  154. package/src/MastheadMenu.ts +1 -1
  155. package/src/MastheadMobileMenu.ts +1 -1
  156. package/src/MastheadShell.ts +24 -1
  157. package/src/MediaPlayer.ts +2 -2
  158. package/src/MessageStrip.ts +2 -1
  159. package/src/RadioButton.ts +0 -1
  160. package/src/Search.ts +0 -1
  161. package/src/SearchableListBase.ts +3 -3
  162. package/src/SecondaryNavigation.ts +1 -1
  163. package/src/SecondaryNavigationItem.ts +1 -1
  164. package/src/SelectBox.ts +9 -9
  165. package/src/SideNavigationMobile.ts +1 -1
  166. package/src/StepInput.ts +1 -1
  167. package/src/TabNavigation.ts +19 -18
  168. package/src/Table.ts +2 -2
  169. package/src/generated/templates/BreadcrumbsPopoverTemplate.lit.ts +1 -1
  170. package/src/generated/templates/DatePickerPopoverTemplate.lit.ts +1 -1
  171. package/src/generated/templates/DatePickerTemplate.lit.ts +1 -1
  172. package/src/generated/templates/FilterMenuTemplate.lit.ts +2 -2
  173. package/src/generated/themes/AccordionItem.css.ts +1 -1
  174. package/src/generated/themes/Button.css.ts +1 -1
  175. package/src/generated/themes/CountrySelector.css.ts +1 -1
  176. package/src/generated/themes/ListItem.css.ts +1 -1
  177. package/src/generated/themes/MastheadMenu.css.ts +1 -1
  178. package/src/generated/themes/MastheadMobileMenu.css.ts +1 -1
  179. package/src/generated/themes/MastheadProfileMenu.css.ts +1 -1
  180. package/src/generated/themes/MessageStrip.css.ts +1 -1
  181. package/src/generated/themes/PhoneNumberField.css.ts +1 -1
  182. package/src/generated/themes/RatingIndicator.css.ts +1 -1
  183. package/src/generated/themes/Review.css.ts +1 -1
  184. package/src/generated/themes/ReviewItem.css.ts +1 -1
  185. package/src/generated/themes/Search.css.ts +1 -1
  186. package/src/generated/themes/SegmentedButton.css.ts +1 -1
  187. package/src/generated/themes/SideNavigationMobileDropdown.css.ts +1 -1
  188. package/src/generated/themes/Slider.css.ts +1 -1
  189. package/src/generated/themes/StepInput.css.ts +1 -1
  190. package/src/generated/themes/TabNavigation.css.ts +1 -1
  191. package/src/generated/themes/Table.css.ts +1 -1
  192. package/src/themes/AccordionItem.css +2 -2
  193. package/src/themes/Button.css +5 -5
  194. package/src/themes/CountrySelector.css +14 -14
  195. package/src/themes/ListItem.css +1 -1
  196. package/src/themes/MastheadMenu.css +2 -2
  197. package/src/themes/MastheadMobileMenu.css +2 -2
  198. package/src/themes/MastheadProfileMenu.css +2 -2
  199. package/src/themes/MessageStrip.css +6 -6
  200. package/src/themes/PhoneNumberField.css +2 -2
  201. package/src/themes/Review.css +1 -1
  202. package/src/themes/ReviewItem.css +1 -1
  203. package/src/themes/Search.css +7 -1
  204. package/src/themes/SegmentedButton.css +1 -1
  205. package/src/themes/SelectBox.css +1 -1
  206. package/src/themes/SideNavigationMobileDropdown.css +1 -1
  207. package/src/themes/StepInput.css +5 -5
  208. package/src/themes/TabNavigation.css +6 -6
  209. package/src/themes/Table.css +5 -5
@@ -4,7 +4,7 @@ import property from "@ui5/webcomponents-base/dist/decorators/property.js";
4
4
  import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
5
5
  import event from "@ui5/webcomponents-base/dist/decorators/event.js";
6
6
  import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
7
- import "@ui5/webcomponents/dist/Icon.js";
7
+ import Icon from "@ui5/webcomponents/dist/Icon.js";
8
8
  import "@ui5/webcomponents-icons/dist/AllIcons.js";
9
9
  import "@ui5/webcomponents-icons/dist/feeder-arrow.js";
10
10
  import { isDesktop } from "@ui5/webcomponents-base/dist/Device.js";
@@ -42,7 +42,7 @@ type ToggleAllEvent = {
42
42
  renderer: litRender,
43
43
  styles: AccordionItemCss,
44
44
  template: AccordionItemTemplate,
45
- dependencies: [UDExBadge],
45
+ dependencies: [UDExBadge, Icon],
46
46
  })
47
47
 
48
48
  /**
package/src/Badge.ts CHANGED
@@ -4,6 +4,7 @@ import property from "@ui5/webcomponents-base/dist/decorators/property.js";
4
4
  import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
5
5
  import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
6
6
  import "@ui5/webcomponents/dist/Badge.js";
7
+ import Icon from "@ui5/webcomponents/dist/Icon.js";
7
8
 
8
9
  import BadgeTemplate from "./generated/templates/BadgeTemplate.lit.js";
9
10
 
@@ -44,7 +45,7 @@ export enum BadgeSize {
44
45
  renderer: litRender,
45
46
  styles: BadgeCss,
46
47
  template: BadgeTemplate,
47
- dependencies: [],
48
+ dependencies: [Icon],
48
49
  })
49
50
  class UDExBadge extends UI5Element {
50
51
  /**
@@ -10,9 +10,9 @@
10
10
  aria-label="{{_dropdownArrowAccessibleNameText}}"
11
11
  aria-haspopup="true">
12
12
  <ui5-icon
13
- name="slim-arrow-down"
14
- title="{{_dropdownArrowAccessibleNameText}}">
15
- </ui5-icon>
13
+ name="slim-arrow-down"
14
+ title="{{_dropdownArrowAccessibleNameText}}">
15
+ </ui5-icon>
16
16
  </button>
17
17
  </li>
18
18
  {{#each _linksData}}
@@ -19,8 +19,8 @@ import breadcrumbsCss from "@ui5/webcomponents/dist/generated/themes/Breadcrumbs
19
19
  import BreadcrumbsTemplate from "./generated/templates/BreadcrumbsTemplate.lit.js";
20
20
  import BreadcrumbsPopover from "./generated/templates/BreadcrumbsPopoverTemplate.lit.js";
21
21
  import UDExBreadcrumbsItem from "./BreadcrumbsItem.js";
22
- import Link from "./Link.js";
23
- import Dropdown from "./Dropdown.js";
22
+ import UDExDropdown from "./Dropdown.js";
23
+ import UDExLink from "./Link.js";
24
24
  import {
25
25
  BREADCRUMBS_ARIA_LABEL,
26
26
  BREADCRUMBS_OVERFLOW_ARIA_LABEL,
@@ -66,7 +66,7 @@ export type UDExBreadcrumbsItemClickEventDetail = {
66
66
  template: BreadcrumbsTemplate,
67
67
  staticAreaTemplate: BreadcrumbsPopover,
68
68
  staticAreaStyles: [BreadcrumbsPopoverCss],
69
- dependencies: [UDExBreadcrumbsItem, Link, Dropdown, Icon],
69
+ dependencies: [UDExBreadcrumbsItem, UDExLink, UDExDropdown, Icon],
70
70
  })
71
71
  /**
72
72
  * Fires when a `BreadcrumbsItem` is clicked.
@@ -132,7 +132,7 @@ class UDExBreadcrumbs extends UI5Element {
132
132
  @slot({ type: HTMLElement, invalidateOnChildChange: true, "default": true })
133
133
  items!: Array<UDExBreadcrumbsItem>;
134
134
 
135
- responsivePopover?: Dropdown;
135
+ responsivePopover?: UDExDropdown;
136
136
  _itemNavigation?: ItemNavigation;
137
137
  _shouldFocusFirstVisibleItem!: boolean;
138
138
 
@@ -156,12 +156,12 @@ class UDExBreadcrumbs extends UI5Element {
156
156
  });
157
157
  }
158
158
 
159
- async _getResponsePopover(): Promise<Dropdown> {
159
+ async _getResponsePopover(): Promise<UDExDropdown> {
160
160
  const staticAreaItem = await this.getStaticAreaItemDomRef();
161
- return staticAreaItem!.querySelector<Dropdown>(`#udex-${this.__id!}-breadcrumbs__popover`)!;
161
+ return staticAreaItem!.querySelector<UDExDropdown>(`#udex-${this.__id!}-breadcrumbs__popover`)!;
162
162
  }
163
163
 
164
- _getFocusableItems(): Array<Link> {
164
+ _getFocusableItems(): Array<UDExLink> {
165
165
  const items = this._links;
166
166
  items.unshift(this._dropdownArrowLink);
167
167
 
@@ -206,7 +206,7 @@ class UDExBreadcrumbs extends UI5Element {
206
206
  }
207
207
 
208
208
  _onLinkPress(e: CustomEvent<LinkClickEventDetail>): void {
209
- const link = e.target as Link,
209
+ const link = e.target as UDExLink,
210
210
  items = this._getItems(),
211
211
  item = items.find(x => `${x._id}-link` === link.id)!,
212
212
  {
@@ -251,7 +251,7 @@ class UDExBreadcrumbs extends UI5Element {
251
251
  }
252
252
 
253
253
  _onfocusin(e: FocusEvent): void {
254
- const currentItem = e.target as Link;
254
+ const currentItem = e.target as UDExLink;
255
255
 
256
256
  this._itemNavigation?.setCurrentItem(currentItem);
257
257
  }
@@ -272,7 +272,7 @@ class UDExBreadcrumbs extends UI5Element {
272
272
  }
273
273
 
274
274
  _focusFirstVisibleItem(): void {
275
- Array.from(this.shadowRoot!.querySelectorAll<Link>("[udex-link]"))[0].focus();
275
+ Array.from(this.shadowRoot!.querySelectorAll<UDExLink>("[udex-link]"))[0].focus();
276
276
  this._shouldFocusFirstVisibleItem = false;
277
277
  }
278
278
 
@@ -280,15 +280,15 @@ class UDExBreadcrumbs extends UI5Element {
280
280
  * Getter for the interactive element that opens the overflow
281
281
  * @private
282
282
  */
283
- get _dropdownArrowLink(): Link {
284
- return this.shadowRoot!.querySelector<Link>(".udex-breadcrumbs__trigger")!;
283
+ get _dropdownArrowLink(): UDExLink {
284
+ return this.shadowRoot!.querySelector<UDExLink>(".udex-breadcrumbs__trigger")!;
285
285
  }
286
286
 
287
287
  /**
288
288
  * Getter for the list of links corresponding to the abstract breadcrumb items
289
289
  */
290
- get _links(): Array<Link> {
291
- return Array.from(this.shadowRoot!.querySelectorAll<Link>(".udex-breadcrumbs__link-wrapper [ui5-link]"));
290
+ get _links(): Array<UDExLink> {
291
+ return Array.from(this.shadowRoot!.querySelectorAll<UDExLink>(".udex-breadcrumbs__link-wrapper [ui5-link]"));
292
292
  }
293
293
 
294
294
  /**
@@ -17,7 +17,7 @@
17
17
  target="{{this.target}}"
18
18
  class="udex-breadcrumbs__item udex-breadcrumbs__item--{{@index}} udex-breadcrumbs__item--with-icon"
19
19
  icon={{this.icon}}
20
- icon-placement="start"
20
+ icon-placement="Start"
21
21
  accessible-name="{{this.textContent}}"
22
22
  data-ui5-stable="{{this.stableDomRef}}">
23
23
  {{this.textContent}}
@@ -350,7 +350,7 @@ class CountrySelector extends UDExSearchableListBase {
350
350
  }
351
351
 
352
352
  get ariaControls(): string | null | undefined {
353
- const list = this.shadowRoot!.querySelector<UDExList>("udex-list");
353
+ const list = this.shadowRoot!.querySelector<UDExList>("[udex-list]");
354
354
  return list?.getAttribute("id");
355
355
  }
356
356
 
@@ -415,7 +415,7 @@ class CountrySelector extends UDExSearchableListBase {
415
415
  }
416
416
 
417
417
  handleCloseSearch() {
418
- this.getInput()?.shadowRoot!.querySelector<Button>("udex-control-button")?.focus();
418
+ this.getInput()?.shadowRoot!.querySelector<Button>("[udex-control-button]")?.focus();
419
419
  }
420
420
 
421
421
  handleItemPress(e: CustomEvent) {
@@ -529,7 +529,7 @@ class CountrySelector extends UDExSearchableListBase {
529
529
  }
530
530
 
531
531
  getSearch(): Search {
532
- return this.shadowRoot!.querySelector<Search>("udex-search")!;
532
+ return this.shadowRoot!.querySelector<Search>("[udex-search]")!;
533
533
  }
534
534
 
535
535
  getDropdownPopover() {
@@ -537,11 +537,11 @@ class CountrySelector extends UDExSearchableListBase {
537
537
  }
538
538
 
539
539
  getDropdown(): UDExDropdown {
540
- return this.shadowRoot!.querySelector<UDExDropdown>("udex-dropdown")!;
540
+ return this.shadowRoot!.querySelector<UDExDropdown>("[udex-dropdown]")!;
541
541
  }
542
542
 
543
543
  getInput(): UDExTextField {
544
- return this.shadowRoot!.querySelector<UDExTextField>("udex-text-field")!;
544
+ return this.shadowRoot!.querySelector<UDExTextField>("[udex-text-field]")!;
545
545
  }
546
546
 
547
547
  get effectiveAriaLabel(): string {
@@ -1,10 +1,9 @@
1
1
  <div
2
2
  class="udex-date-picker__container">
3
3
  <udex-text-field
4
- @click="{{handleInputClick}}"
5
- @mousedown="{{handleInputMouseDown}}"
6
- @keydown="{{handleInputKeyDown}}"
7
- class="udex-date-picker__input udex-date-picker__trigger"
4
+ value="{{value}}"
5
+ @ui5-change="{{_onInputChange}}"
6
+ class="udex-date-picker__input"
8
7
  label="{{label}}"
9
8
  accessible-name="{{dateAccessibleName}}"
10
9
  accessible-name-ref="{{accessibleNameRef}}"
@@ -13,8 +12,8 @@
13
12
  ?disabled="{{disabled}}"
14
13
  ?required="{{required}}"
15
14
  ?readonly="{{readonly}}"
16
- value="{{value}}"
17
15
  icon="appointment-2"
16
+ @ui5-click-icon="{{handleInputClick}}"
18
17
  value-state="{{valueState}}"
19
18
  >
20
19
  </udex-text-field>
package/src/DatePicker.ts CHANGED
@@ -1,11 +1,11 @@
1
- import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
1
+ import DateComponentBase from "@ui5/webcomponents/dist/DateComponentBase.js";
2
2
  import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
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 event from "@ui5/webcomponents-base/dist/decorators/event.js";
6
6
  // eslint-disable-next-line
7
7
  import Calendar, { CalendarSelectedDatesChangeEventDetail } from "@ui5/webcomponents/dist/Calendar.js";
8
- import CalendarDate from "@ui5/webcomponents/dist/CalendarDate.js";
8
+ import CalendarDateComponent from "@ui5/webcomponents/dist/CalendarDate.js";
9
9
  import "@ui5/webcomponents/dist/Icon.js";
10
10
  import "@ui5/webcomponents-icons/dist/appointment-2.js";
11
11
  import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
@@ -31,7 +31,7 @@ export enum UDExDatePickerSelectionMode {
31
31
 
32
32
  export type DatePickerSelectionChangeEventDetail = {
33
33
  selectedValues: Array<string>;
34
- selectedDates: Array<number>;
34
+ selectedDates: Array<number | undefined>;
35
35
  timestamp: number | undefined;
36
36
  };
37
37
 
@@ -50,7 +50,7 @@ export type DatePickerSelectionChangeEventDetail = {
50
50
  *
51
51
  * @constructor
52
52
  * @author SAP SE
53
- * @extends UI5Element
53
+ * @extends DateComponentBase
54
54
  * @tagname udex-date-picker
55
55
  * @public
56
56
  */
@@ -61,7 +61,7 @@ export type DatePickerSelectionChangeEventDetail = {
61
61
  template: DatePickerTemplate,
62
62
  staticAreaTemplate: DatePickerPopover,
63
63
  staticAreaStyles: [DatePickerPopoverCss],
64
- dependencies: [CalendarDate, Calendar, UDExTextField, UDExDropdown, UDExStatusMessage],
64
+ dependencies: [CalendarDateComponent, Calendar, UDExTextField, UDExDropdown, UDExStatusMessage],
65
65
  })
66
66
  /**
67
67
  * Fired when the selected dates change.
@@ -85,7 +85,7 @@ export type DatePickerSelectionChangeEventDetail = {
85
85
  timestamp: { type: Number },
86
86
  },
87
87
  })
88
- class UDExDatePicker extends UI5Element {
88
+ class UDExDatePicker extends DateComponentBase {
89
89
  /**
90
90
  * Defines selection mode of the calendar component.
91
91
  *
@@ -171,28 +171,6 @@ class UDExDatePicker extends UI5Element {
171
171
  @property({ type: String, defaultValue: "" })
172
172
  label!: string;
173
173
 
174
- /**
175
- * Determines the minimum date available for selection.
176
- * <br/><br/>
177
- * <b>Note:</b> The minDate value must be provided in the ISO date format (YYYY-MM-dd).
178
- *
179
- * @default ""
180
- * @public
181
- */
182
- @property({ type: String, defaultValue: "" })
183
- minDate!: string;
184
-
185
- /**
186
- * Determines the maximum date available for selection.
187
- * <br/><br/>
188
- * <b>Note:</b> The maxDate value must be provided in the ISO date format (YYYY-MM-dd).
189
- *
190
- * @default ""
191
- * @public
192
- */
193
- @property({ type: String, defaultValue: "" })
194
- maxDate!: string;
195
-
196
174
  /**
197
175
  * Defines selected dates values.
198
176
  *
@@ -219,19 +197,23 @@ class UDExDatePicker extends UI5Element {
219
197
  @property({ type: String, defaultValue: "MMM dd, yyyy" })
220
198
  formatPattern!: string;
221
199
 
200
+ /**
201
+ * The first date in the range during selection (this is a temporary value, not the first date in the value range)
202
+ * @private
203
+ */
204
+ @property()
205
+ _tempValue!: string;
206
+
222
207
  responsivePopover?: UDExDropdown;
223
208
 
224
209
  static i18nBundle: I18nBundle;
225
210
 
211
+ private _prevDelimiter!: string | null;
212
+
226
213
  static async onDefine(): Promise<void> {
227
214
  UDExDatePicker.i18nBundle = await getI18nBundle("@udex/web-components");
228
215
  }
229
216
 
230
- async _getCalendar(): Promise<Calendar> {
231
- const staticAreaItem = await this.getStaticAreaItemDomRef();
232
- return staticAreaItem!.querySelector<Calendar>("#ui5-calendar")!;
233
- }
234
-
235
217
  async _getResponsePopover(): Promise<UDExDropdown> {
236
218
  const staticAreaItem = await this.getStaticAreaItemDomRef();
237
219
  return staticAreaItem!.querySelector<UDExDropdown>(`#udex-${this.__id!}-calendar__popover`)!;
@@ -242,12 +224,13 @@ class UDExDatePicker extends UI5Element {
242
224
  * @private
243
225
  */
244
226
  get _dropdownTrigger(): UDExTextField {
245
- return this.shadowRoot!.querySelector<UDExTextField>(".udex-date-picker__trigger")!;
227
+ return this.shadowRoot!.querySelector<UDExTextField>(".udex-date-picker__input")!;
246
228
  }
247
229
 
248
230
  _afterDropdownClose(): void {
249
231
  this._dropdownTrigger.active = false;
250
- this._dropdownTrigger.shadowRoot?.querySelector("input")?.focus();
232
+ this._dropdownTrigger.shadowRoot?.querySelector("input")?.blur();
233
+ this._tempValue = "";
251
234
  }
252
235
 
253
236
  _afterDropdownOpen(): void {
@@ -273,35 +256,251 @@ class UDExDatePicker extends UI5Element {
273
256
  }
274
257
 
275
258
  handleCalendarChange(e: CustomEvent<CalendarSelectedDatesChangeEventDetail>): void {
276
- const { dates, timestamp, values } = e.detail;
259
+ e.preventDefault();
260
+ if (this.selectionMode === UDExDatePickerSelectionMode.Single) {
261
+ const newValue = e.detail.values && e.detail.values[0];
262
+ this._updateValueAndFireEvents(newValue, true, e);
263
+ }
264
+
265
+ if (this.selectionMode === UDExDatePickerSelectionMode.Range) {
266
+ const values = e.detail.values;
267
+
268
+ if (values.length === 0) {
269
+ return;
270
+ }
271
+
272
+ if (values.length === 1) { // Do nothing until the user selects 2 dates, we don't change any state at all for one date
273
+ this._tempValue = values[0];
274
+ return;
275
+ }
277
276
 
278
- const formattedValues = values;
277
+ const newValue = this._buildValue(e.detail.dates[0], e.detail.dates[1]);
278
+ this._updateValueAndFireEvents(newValue, true, e);
279
+ }
280
+
281
+ this.hideCalendar();
282
+ }
283
+
284
+ get _effectiveDelimiter(): string {
285
+ return "-";
286
+ }
287
+
288
+ _getInput(): HTMLInputElement | null | undefined {
289
+ return this._dropdownTrigger.shadowRoot?.querySelector("input");
290
+ }
291
+
292
+ _splitValueByDelimiter(value: string) {
293
+ const valuesArray: Array<string> = [];
294
+ const partsArray = value.split(this._prevDelimiter || this._effectiveDelimiter);
279
295
 
296
+ // if format successfully parse the value, the value contains only single date
297
+ if (this.getFormat().parse(value)) {
298
+ valuesArray[0] = partsArray.join(this._effectiveDelimiter);
299
+ valuesArray[1] = "";
300
+
301
+ return valuesArray;
302
+ }
303
+
304
+ valuesArray[0] = partsArray.slice(0, partsArray.length / 2).join(this._effectiveDelimiter);
305
+ valuesArray[1] = partsArray.slice(partsArray.length / 2).join(this._effectiveDelimiter);
306
+
307
+ return valuesArray;
308
+ }
309
+
310
+ /**
311
+ * Returns a UTC timestamp, representing the last date in the value string or undefined if the value is empty or there is just one date
312
+ * @private
313
+ */
314
+ _extractLastTimestamp(value: string) {
315
+ if (!value || !this._checkValueValidity(value)) {
316
+ return undefined;
317
+ }
318
+
319
+ const dateStrings = this._splitValueByDelimiter(value);
320
+ if (dateStrings[1]) {
321
+ const parsedDate = this.getFormat().parse(dateStrings[1], true) as Date;
322
+ return parsedDate.getTime() / 1000;
323
+ }
324
+
325
+ return undefined;
326
+ }
327
+
328
+ /**
329
+ * Returns a UTC timestamp, representing the first date in the value string or undefined if the value is empty
330
+ * @private
331
+ */
332
+ _extractFirstTimestamp(value: string) {
333
+ if (!value || !this._checkValueValidity(value)) {
334
+ return undefined;
335
+ }
336
+
337
+ const dateStrings = this._splitValueByDelimiter(value); // at least one item guaranteed due to the checks above (non-empty and valid)
338
+
339
+ const parsedDate = this.getFormat().parse(dateStrings[0], true) as Date;
340
+ return parsedDate.getTime() / 1000;
341
+ }
342
+
343
+ /**
344
+ * Checks if a value is valid against the current date format of the DatePicker.
345
+ * @public
346
+ * @param value A value to be tested against the current date format
347
+ */
348
+ isValid(value: string): boolean {
349
+ if (value === "" || value === undefined) {
350
+ return true;
351
+ }
352
+
353
+ return !!this.getFormat().parse(value);
354
+ }
355
+
356
+ isValidRange(value: string): boolean {
357
+ const parts = this._splitValueByDelimiter(value);
358
+ return parts.length <= 2 && parts.every(dateString => this.isValid(dateString)); // must be at most 2 dates and each must be valid
359
+ }
360
+
361
+ isInValidRange(value: string): boolean {
362
+ if (value === "" || value === undefined) {
363
+ return true;
364
+ }
365
+
366
+ const calendarDate = this._getCalendarDateFromString(value);
367
+
368
+ if (!calendarDate || !this._minDate || !this._maxDate) {
369
+ return false;
370
+ }
371
+
372
+ return calendarDate.valueOf() >= this._minDate.valueOf() && calendarDate.valueOf() <= this._maxDate.valueOf();
373
+ }
374
+
375
+ /**
376
+ * Checks if a date is between the minimum and maximum date.
377
+ * @public
378
+ * @param value A value to be checked
379
+ */
380
+ isInValidRangeRange(value: string): boolean {
381
+ return this._splitValueByDelimiter(value).every(dateString => this.isInValidRange(dateString));
382
+ }
383
+
384
+ _checkValueValidity(value: string): boolean {
385
+ let result = false;
386
+ if (value === "") {
387
+ return true;
388
+ }
280
389
  if (this.selectionMode === UDExDatePickerSelectionMode.Single) {
281
- this.value = formattedValues[0];
282
- this.selectedDates = formattedValues[0];
390
+ result = this.isValid(value) && this.isInValidRange(value);
391
+ }
392
+ if (this.selectionMode === UDExDatePickerSelectionMode.Range) {
393
+ result = this.isValidRange(value) && this.isInValidRangeRange(value);
394
+ }
395
+ return result;
396
+ }
397
+
398
+ /**
399
+ * Builds a string value out of two UTC timestamps - this method is the counterpart to _extractFirstTimestamp/_extractLastTimestamp
400
+ * @private
401
+ */
402
+ _buildValue(firstDateTimestamp: number | undefined, lastDateTimestamp: number | undefined) {
403
+ this._prevDelimiter = this._effectiveDelimiter;
404
+ if (firstDateTimestamp) {
405
+ const firstDateString = this._getStringFromTimestamp(firstDateTimestamp * 1000);
406
+
407
+ if (!lastDateTimestamp) {
408
+ return firstDateString;
409
+ }
410
+
411
+ const lastDateString = this._getStringFromTimestamp(lastDateTimestamp * 1000);
412
+ return `${firstDateString} ${this._effectiveDelimiter} ${lastDateString}`;
283
413
  }
284
414
 
415
+ return "";
416
+ }
417
+
418
+ /**
419
+ * The parser understands many formats, but we need one format OR extract both dates as timestamps, flip if necessary, and build (which will use the desired format so we enforce the format too)
420
+ * @protected
421
+ */
422
+ normalizeValue(value: string) {
423
+ let result = "";
424
+ if (this.selectionMode === UDExDatePickerSelectionMode.Single) {
425
+ if (value === "") {
426
+ return value;
427
+ }
428
+ result = this.getFormat().format(this.getFormat().parse(value, true), true); // it is important to both parse and format the date as UTC
429
+ }
285
430
  if (this.selectionMode === UDExDatePickerSelectionMode.Range) {
286
- if (dates.length < 2) {
287
- return;
431
+ const firstDateTimestamp = this._extractFirstTimestamp(value);
432
+ const lastDateTimestamp = this._extractLastTimestamp(value);
433
+ if (firstDateTimestamp && lastDateTimestamp && firstDateTimestamp > lastDateTimestamp) { // if both are timestamps (not undefined), flip if necessary
434
+ return this._buildValue(lastDateTimestamp, firstDateTimestamp);
288
435
  }
436
+ result = this._buildValue(firstDateTimestamp, lastDateTimestamp);
437
+ }
438
+ return result;
439
+ }
440
+
441
+ _updateValueState() {
442
+ const valid = this._checkValueValidity(this.value);
443
+ const previousValueState = this.valueState;
444
+
445
+ this.valueState = valid ? ValueState.Standard : ValueState.Error;
446
+
447
+ const eventPrevented = !this.fireEvent("value-state-change", { valueState: this.valueState, valid });
448
+
449
+ if (eventPrevented) {
450
+ this.valueState = previousValueState;
451
+ }
452
+ }
289
453
 
290
- this.value = `${formattedValues[0]} - ${formattedValues[1]}`;
291
- this.selectedDates = `${formattedValues[0]}, ${formattedValues[1]}`;
454
+ _buildEventData(value: string): DatePickerSelectionChangeEventDetail {
455
+ if (this.selectionMode === UDExDatePickerSelectionMode.Range) {
456
+ return {
457
+ selectedDates: [this._extractFirstTimestamp(value), this._extractLastTimestamp(value)],
458
+ selectedValues: this._splitValueByDelimiter(this.value),
459
+ timestamp: this._extractLastTimestamp(value),
460
+ };
292
461
  }
462
+ return {
463
+ selectedDates: [this._extractFirstTimestamp(value)],
464
+ selectedValues: [value],
465
+ timestamp: this._extractFirstTimestamp(value),
466
+ };
467
+ }
293
468
 
294
- this.fireEvent(
295
- "selection-change",
296
- {
297
- timestamp,
298
- selectedDates: [...dates],
299
- selectedValues: formattedValues,
300
- },
301
- true,
302
- );
469
+ _updateValueAndFireEvents(value: string, normalizeValue: boolean, e?: CustomEvent<CalendarSelectedDatesChangeEventDetail> | null) {
470
+ const valid = this._checkValueValidity(value);
303
471
 
304
- this.hideCalendar();
472
+ if (valid && normalizeValue) {
473
+ value = this.normalizeValue(value); // transform valid values (in any format) to the correct format
474
+ }
475
+
476
+ this.value = value;
477
+ this._updateValueState(); // Change the value state to Error/None, but only if needed
478
+
479
+ if (!valid) { return; }
480
+
481
+ if (e) {
482
+ const { dates, timestamp, values } = e.detail;
483
+
484
+ this.fireEvent(
485
+ "selection-change",
486
+ {
487
+ timestamp,
488
+ selectedDates: [...dates],
489
+ selectedValues: values,
490
+ },
491
+ true,
492
+ );
493
+ } else {
494
+ this.fireEvent(
495
+ "selection-change",
496
+ this._buildEventData(value),
497
+ true,
498
+ );
499
+ }
500
+ }
501
+
502
+ _onInputChange(e: Event) {
503
+ this._updateValueAndFireEvents((e.target as UDExDatePicker).value, true);
305
504
  }
306
505
 
307
506
  handleInputClick(e: Event | KeyboardEvent): void {
@@ -314,23 +513,17 @@ class UDExDatePicker extends UI5Element {
314
513
  this.showCalendar();
315
514
  }
316
515
 
317
- handleInputMouseDown(e: Event): void {
318
- e.preventDefault();
319
- }
320
-
321
- handleInputKeyDown(e: KeyboardEvent): void {
322
- if (e.key === "Enter") {
323
- this.handleInputClick(e);
324
- }
325
- }
326
-
327
516
  /**
328
517
  * Used to provide selectedDates to the calendar based on the component's state
329
518
  * Override in derivatives to provide different rules for setting the calendar's selected dates
330
519
  * @protected
331
520
  */
332
521
  get _calendarSelectedDates(): Array<string> {
333
- if (this.value) {
522
+ if (this._tempValue) {
523
+ return [this._tempValue];
524
+ }
525
+
526
+ if (this.value && this._checkValueValidity(this.value)) {
334
527
  return this.value.split(" - ");
335
528
  }
336
529
 
@@ -3,8 +3,8 @@
3
3
  class="udex-date-picker__popover"
4
4
  placement-type="Bottom"
5
5
  horizontal-align="Left"
6
- @after-close="{{_afterDropdownClose}}"
7
- @after-open="{{_afterDropdownOpen}}"
6
+ @ui5-after-close="{{_afterDropdownClose}}"
7
+ @ui5-after-open="{{_afterDropdownOpen}}"
8
8
  >
9
9
  <ui5-calendar
10
10
  class="udex-date-picker__calendar"
@@ -67,7 +67,7 @@
67
67
  class="udex-filter-menu__result-btn"
68
68
  size="Medium"
69
69
  design="Primary"
70
- ?disabled="{{disabledResultBtn}}"
70
+ ?disabled="{{disabledButtons}}"
71
71
  @keydown="{{handleKeyDownResultBtn}}"
72
72
  @click="{{handleResult}}">
73
73
  {{getResultLabelText}}
@@ -79,6 +79,7 @@
79
79
  size="Medium"
80
80
  design="Tertiary"
81
81
  @keydown="{{handleKeyDownResetBtn}}"
82
+ ?disabled="{{disabledButtons}}"
82
83
  @click="{{handleReset}}">
83
84
  {{getResetLabelText}}
84
85
  </udex-button>