Skip to content

Commit 3e684b4

Browse files
authored
feat: refactoring and new features for pickers (#2598)
1 parent 0120960 commit 3e684b4

File tree

77 files changed

+3413
-5017
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+3413
-5017
lines changed

packages/base/src/Keys.js

+6
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,12 @@ const KeyCodes = {
105105

106106
const isEnter = event => (event.key ? event.key === "Enter" : event.keyCode === KeyCodes.ENTER) && !hasModifierKeys(event);
107107

108+
const isEnterShift = event => (event.key ? event.key === "Enter" : event.keyCode === KeyCodes.ENTER) && checkModifierKeys(event, false, false, true);
109+
108110
const isSpace = event => (event.key ? (event.key === "Spacebar" || event.key === " ") : event.keyCode === KeyCodes.SPACE) && !hasModifierKeys(event);
109111

112+
const isSpaceShift = event => (event.key ? (event.key === "Spacebar" || event.key === " ") : event.keyCode === KeyCodes.SPACE) && checkModifierKeys(event, false, false, true);
113+
110114
const isLeft = event => (event.key ? (event.key === "ArrowLeft" || event.key === "Left") : event.keyCode === KeyCodes.ARROW_LEFT) && !hasModifierKeys(event);
111115

112116
const isRight = event => (event.key ? (event.key === "ArrowRight" || event.key === "Right") : event.keyCode === KeyCodes.ARROW_RIGHT) && !hasModifierKeys(event);
@@ -171,7 +175,9 @@ const checkModifierKeys = (event, bCtrlKey, bAltKey, bShiftKey) => event.shiftKe
171175

172176
export {
173177
isEnter,
178+
isEnterShift,
174179
isSpace,
180+
isSpaceShift,
175181
isLeft,
176182
isRight,
177183
isUp,

packages/base/src/UI5Element.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -997,11 +997,17 @@ class UI5Element extends HTMLElement {
997997
}
998998
},
999999
set(value) {
1000+
let isDifferent;
10001001
value = this.constructor.getMetadata().constructor.validatePropertyValue(value, propData);
10011002

10021003
const oldState = this._state[prop];
1004+
if (propData.multiple && propData.compareValues) {
1005+
isDifferent = !arraysAreEqual(oldState, value);
1006+
} else {
1007+
isDifferent = oldState !== value;
1008+
}
10031009

1004-
if (oldState !== value) {
1010+
if (isDifferent) {
10051011
this._state[prop] = value;
10061012
_invalidate.call(this, {
10071013
type: "property",

packages/base/src/delegate/ItemNavigation.js

+5-85
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import {
66
isRight,
77
isHome,
88
isEnd,
9-
isPageUp,
10-
isPageDown,
119
} from "../Keys.js";
1210
import getActiveElement from "../util/getActiveElement.js";
1311

@@ -23,7 +21,6 @@ import ItemNavigationBehavior from "../types/ItemNavigationBehavior.js";
2321
* - Up/down
2422
* - Left/right
2523
* - Home/End
26-
* - PageUp/PageDown
2724
*
2825
* Usage:
2926
* 1) Use the "getItemsCallback" constructor property to pass a callback to ItemNavigation, which, whenever called, will return the list of items to navigate among.
@@ -57,11 +54,9 @@ class ItemNavigation extends EventProvider {
5754
* - currentIndex: the index of the item that will be initially selected (from which navigation will begin)
5855
* - navigationMode (Auto|Horizontal|Vertical): whether the items are displayed horizontally (Horizontal), vertically (Vertical) or as a matrix (Auto) meaning the user can navigate in both directions (up/down and left/right)
5956
* - rowSize: tells how many items per row there are when the items are not rendered as a flat list but rather as a matrix. Relevant for navigationMode=Auto
60-
* - behavior (Static|Cycling|Paging): tells what to do when trying to navigate beyond the first and last items
57+
* - behavior (Static|Cycling): tells what to do when trying to navigate beyond the first and last items
6158
* Static means that nothing happens if the user tries to navigate beyond the first/last item.
6259
* Cycling means that when the user navigates beyond the last item they go to the first and vice versa.
63-
* Paging means that when the urse navigates beyond the first/last item, a new "page" of items appears (as commonly observed with calendars for example)
64-
* - pageSize: tells how many items the user skips by using the PageUp/PageDown keys
6560
* - getItemsCallback: function that, when called, returns an array with all items the user can navigate among
6661
* - affectedPropertiesNames: a list of metadata properties on the root component which, upon user navigation, will be reassigned by address thus causing the root component to invalidate
6762
*/
@@ -76,8 +71,6 @@ class ItemNavigation extends EventProvider {
7671
this.horizontalNavigationOn = autoNavigation || navigationMode === NavigationMode.Horizontal;
7772
this.verticalNavigationOn = autoNavigation || navigationMode === NavigationMode.Vertical;
7873

79-
this.pageSize = options.pageSize;
80-
8174
if (options.affectedPropertiesNames) {
8275
this.affectedPropertiesNames = options.affectedPropertiesNames;
8376
}
@@ -86,10 +79,6 @@ class ItemNavigation extends EventProvider {
8679
this._getItems = options.getItemsCallback;
8780
}
8881

89-
const trueFunction = () => true;
90-
this._hasNextPage = typeof options.hasNextPageCallback === "function" ? options.hasNextPageCallback : trueFunction;
91-
this._hasPreviousPage = typeof options.hasPreviousPageCallback === "function" ? options.hasPreviousPageCallback : trueFunction;
92-
9382
this.rootWebComponent = rootWebComponent;
9483
this.rootWebComponent.addEventListener("keydown", this.onkeydown.bind(this));
9584
this.rootWebComponent._onComponentStateFinalized = () => {
@@ -113,9 +102,9 @@ class ItemNavigation extends EventProvider {
113102

114103
async _onKeyPress(event) {
115104
if (this.currentIndex >= this._getItems().length) {
116-
this.onOverflowBottomEdge(event);
105+
this.onOverflowBottomEdge();
117106
} else if (this.currentIndex < 0) {
118-
this.onOverflowTopEdge(event);
107+
this.onOverflowTopEdge();
119108
}
120109

121110
event.preventDefault();
@@ -124,7 +113,6 @@ class ItemNavigation extends EventProvider {
124113

125114
this.update();
126115
this.focusCurrent();
127-
this.fireEvent(ItemNavigation.AFTER_FOCUS);
128116
}
129117

130118
onkeydown(event) {
@@ -151,14 +139,6 @@ class ItemNavigation extends EventProvider {
151139
if (isEnd(event)) {
152140
return this._handleEnd(event);
153141
}
154-
155-
if (isPageUp(event)) {
156-
return this._handlePageUp(event);
157-
}
158-
159-
if (isPageDown(event)) {
160-
return this._handlePageDown(event);
161-
}
162142
}
163143

164144
_handleUp(event) {
@@ -205,20 +185,6 @@ class ItemNavigation extends EventProvider {
205185
}
206186
}
207187

208-
_handlePageUp(event) {
209-
if (this._canNavigate()) {
210-
this.currentIndex -= this.pageSize;
211-
this._onKeyPress(event);
212-
}
213-
}
214-
215-
_handlePageDown(event) {
216-
if (this._canNavigate()) {
217-
this.currentIndex += this.pageSize;
218-
this._onKeyPress(event);
219-
}
220-
}
221-
222188
/**
223189
* Call this method to set a new "current" (selected) item in the item navigation
224190
* Note: the item passed to this function must be one of the items, returned by the getItemsCallback function
@@ -323,71 +289,25 @@ class ItemNavigation extends EventProvider {
323289

324290
onOverflowBottomEdge(event) {
325291
const items = this._getItems();
326-
const offset = (this.currentIndex - items.length) % this.rowSize;
327292

328293
if (this.behavior === ItemNavigationBehavior.Cyclic) {
329294
this.currentIndex = 0;
330295
return;
331296
}
332297

333-
if (this.behavior === ItemNavigationBehavior.Paging) {
334-
this._handleNextPage();
335-
} else {
336-
this.currentIndex = items.length - 1;
337-
}
338-
339-
this.fireEvent(ItemNavigation.BORDER_REACH, {
340-
start: false,
341-
end: true,
342-
originalEvent: event,
343-
offset,
344-
});
298+
this.currentIndex = items.length - 1;
345299
}
346300

347301
onOverflowTopEdge(event) {
348302
const items = this._getItems();
349-
const offsetRight = (this.currentIndex + this.rowSize) % this.rowSize;
350-
const offset = offsetRight < 0 ? (this.rowSize + offsetRight) : offsetRight;
351303

352304
if (this.behavior === ItemNavigationBehavior.Cyclic) {
353305
this.currentIndex = items.length - 1;
354306
return;
355307
}
356308

357-
if (this.behavior === ItemNavigationBehavior.Paging) {
358-
this._handlePrevPage();
359-
} else {
360-
this.currentIndex = 0;
361-
}
362-
363-
this.fireEvent(ItemNavigation.BORDER_REACH, {
364-
start: true,
365-
end: false,
366-
originalEvent: event,
367-
offset,
368-
});
369-
}
370-
371-
_handleNextPage() {
372-
const items = this._getItems();
373-
374-
if (!this._hasNextPage()) {
375-
this.currentIndex = items.length - 1;
376-
} else {
377-
this.currentIndex -= this.pageSize;
378-
}
379-
}
380-
381-
_handlePrevPage() {
382-
if (!this._hasPreviousPage()) {
383-
this.currentIndex = 0;
384-
} else {
385-
this.currentIndex = this.pageSize + this.currentIndex;
386-
}
309+
this.currentIndex = 0;
387310
}
388311
}
389312

390-
ItemNavigation.BORDER_REACH = "_borderReach";
391-
ItemNavigation.AFTER_FOCUS = "_afterFocus";
392-
393313
export default ItemNavigation;

packages/base/src/delegate/ScrollEnablement.js

+24-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,30 @@ class ScrollEnablement extends EventProvider {
4242
return this._container;
4343
}
4444

45-
scrollTo(left, top) {
45+
/**
46+
* Scrolls the container to the left/top position, retrying retryCount times, if the container is not yet painted
47+
*
48+
* @param left
49+
* @param top
50+
* @param retryCount
51+
* @param retryInterval
52+
* @returns {Promise<void>} resolved when scrolled successfully
53+
*/
54+
async scrollTo(left, top, retryCount = 0, retryInterval = 0) {
55+
let containerPainted = this.scrollContainer.clientHeight > 0 && this.scrollContainer.clientWidth > 0;
56+
57+
/* eslint-disable no-loop-func, no-await-in-loop */
58+
while (!containerPainted && retryCount > 0) {
59+
await new Promise(resolve => {
60+
setTimeout(() => {
61+
containerPainted = this.scrollContainer.clientHeight > 0 && this.scrollContainer.clientWidth > 0;
62+
retryCount--;
63+
resolve();
64+
}, retryInterval);
65+
});
66+
}
67+
/* eslint-disable no-loop-func, no-await-in-loop */
68+
4669
this._container.scrollLeft = left;
4770
this._container.scrollTop = top;
4871
}

packages/base/src/features/browsersupport/IE11.js

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import "../../thirdparty/Object.entries.js";
1010
// Array
1111
import "../../thirdparty/Array.prototype.fill.js";
1212
import "../../thirdparty/Array.prototype.find.js";
13+
import "../../thirdparty/Array.prototype.findIndex.js";
1314
import "../../thirdparty/Array.prototype.includes.js";
1415

1516
// Map
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// https://tc39.github.io/ecma262/#sec-array.prototype.findindex
2+
if (!Array.prototype.findIndex) {
3+
Object.defineProperty(Array.prototype, 'findIndex', {
4+
value: function(predicate) {
5+
// 1. Let O be ? ToObject(this value).
6+
if (this == null) {
7+
throw new TypeError('"this" is null or not defined');
8+
}
9+
10+
var o = Object(this);
11+
12+
// 2. Let len be ? ToLength(? Get(O, "length")).
13+
var len = o.length >>> 0;
14+
15+
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
16+
if (typeof predicate !== 'function') {
17+
throw new TypeError('predicate must be a function');
18+
}
19+
20+
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
21+
var thisArg = arguments[1];
22+
23+
// 5. Let k be 0.
24+
var k = 0;
25+
26+
// 6. Repeat, while k < len
27+
while (k < len) {
28+
// a. Let Pk be ! ToString(k).
29+
// b. Let kValue be ? Get(O, Pk).
30+
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
31+
// d. If testResult is true, return k.
32+
var kValue = o[k];
33+
if (predicate.call(thisArg, kValue, k, o)) {
34+
return k;
35+
}
36+
// e. Increase k by 1.
37+
k++;
38+
}
39+
40+
// 7. Return -1.
41+
return -1;
42+
},
43+
configurable: true,
44+
writable: true
45+
});
46+
}

packages/base/src/thirdparty/Element.prototype.closest.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
if (!Element.prototype.closest) {
22
Element.prototype.closest = function(s) {
33
var el = this;
4-
if (!document.documentElement.contains(el)) return null;
4+
55
do {
6-
if (el.matches(s)) return el;
6+
if (Element.prototype.matches.call(el, s)) return el;
77
el = el.parentElement || el.parentNode;
88
} while (el !== null && el.nodeType === 1);
99
return null;

packages/base/src/types/CalendarSelection.js

-17
This file was deleted.

packages/base/src/types/ItemNavigationBehavior.js

+2-7
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,13 @@
44
*/
55
const ItemNavigationBehavior = {
66
/**
7-
* Static behavior: when border of the items is reached, you can't go out of the cage.
7+
* Static behavior: navigations stops at the first or last item.
88
*/
99
Static: "Static",
1010

1111
/**
12-
* Cycling behavior: when border of the items is reached, you can cycle through the items.
12+
* Cycling behavior: navigating past the last item continues with the first and vice versa.
1313
*/
1414
Cyclic: "Cyclic",
15-
16-
/**
17-
* Paging behavior: when border of the items is reached, tou can go up/down based on the rowsize(e.g. DayPicker)
18-
*/
19-
Paging: "Paging",
2015
};
2116
export default ItemNavigationBehavior;

0 commit comments

Comments
 (0)