Skip to content

Commit

Permalink
feat: refactoring and new features for pickers (#2598)
Browse files Browse the repository at this point in the history
  • Loading branch information
vladitasev authored Jan 8, 2021
1 parent 0120960 commit 3e684b4
Show file tree
Hide file tree
Showing 77 changed files with 3,413 additions and 5,017 deletions.
6 changes: 6 additions & 0 deletions packages/base/src/Keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,12 @@ const KeyCodes = {

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

const isEnterShift = event => (event.key ? event.key === "Enter" : event.keyCode === KeyCodes.ENTER) && checkModifierKeys(event, false, false, true);

const isSpace = event => (event.key ? (event.key === "Spacebar" || event.key === " ") : event.keyCode === KeyCodes.SPACE) && !hasModifierKeys(event);

const isSpaceShift = event => (event.key ? (event.key === "Spacebar" || event.key === " ") : event.keyCode === KeyCodes.SPACE) && checkModifierKeys(event, false, false, true);

const isLeft = event => (event.key ? (event.key === "ArrowLeft" || event.key === "Left") : event.keyCode === KeyCodes.ARROW_LEFT) && !hasModifierKeys(event);

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

export {
isEnter,
isEnterShift,
isSpace,
isSpaceShift,
isLeft,
isRight,
isUp,
Expand Down
8 changes: 7 additions & 1 deletion packages/base/src/UI5Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -997,11 +997,17 @@ class UI5Element extends HTMLElement {
}
},
set(value) {
let isDifferent;
value = this.constructor.getMetadata().constructor.validatePropertyValue(value, propData);

const oldState = this._state[prop];
if (propData.multiple && propData.compareValues) {
isDifferent = !arraysAreEqual(oldState, value);
} else {
isDifferent = oldState !== value;
}

if (oldState !== value) {
if (isDifferent) {
this._state[prop] = value;
_invalidate.call(this, {
type: "property",
Expand Down
90 changes: 5 additions & 85 deletions packages/base/src/delegate/ItemNavigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import {
isRight,
isHome,
isEnd,
isPageUp,
isPageDown,
} from "../Keys.js";
import getActiveElement from "../util/getActiveElement.js";

Expand All @@ -23,7 +21,6 @@ import ItemNavigationBehavior from "../types/ItemNavigationBehavior.js";
* - Up/down
* - Left/right
* - Home/End
* - PageUp/PageDown
*
* Usage:
* 1) Use the "getItemsCallback" constructor property to pass a callback to ItemNavigation, which, whenever called, will return the list of items to navigate among.
Expand Down Expand Up @@ -57,11 +54,9 @@ class ItemNavigation extends EventProvider {
* - currentIndex: the index of the item that will be initially selected (from which navigation will begin)
* - 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)
* - 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
* - behavior (Static|Cycling|Paging): tells what to do when trying to navigate beyond the first and last items
* - behavior (Static|Cycling): tells what to do when trying to navigate beyond the first and last items
* Static means that nothing happens if the user tries to navigate beyond the first/last item.
* Cycling means that when the user navigates beyond the last item they go to the first and vice versa.
* 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)
* - pageSize: tells how many items the user skips by using the PageUp/PageDown keys
* - getItemsCallback: function that, when called, returns an array with all items the user can navigate among
* - 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
*/
Expand All @@ -76,8 +71,6 @@ class ItemNavigation extends EventProvider {
this.horizontalNavigationOn = autoNavigation || navigationMode === NavigationMode.Horizontal;
this.verticalNavigationOn = autoNavigation || navigationMode === NavigationMode.Vertical;

this.pageSize = options.pageSize;

if (options.affectedPropertiesNames) {
this.affectedPropertiesNames = options.affectedPropertiesNames;
}
Expand All @@ -86,10 +79,6 @@ class ItemNavigation extends EventProvider {
this._getItems = options.getItemsCallback;
}

const trueFunction = () => true;
this._hasNextPage = typeof options.hasNextPageCallback === "function" ? options.hasNextPageCallback : trueFunction;
this._hasPreviousPage = typeof options.hasPreviousPageCallback === "function" ? options.hasPreviousPageCallback : trueFunction;

this.rootWebComponent = rootWebComponent;
this.rootWebComponent.addEventListener("keydown", this.onkeydown.bind(this));
this.rootWebComponent._onComponentStateFinalized = () => {
Expand All @@ -113,9 +102,9 @@ class ItemNavigation extends EventProvider {

async _onKeyPress(event) {
if (this.currentIndex >= this._getItems().length) {
this.onOverflowBottomEdge(event);
this.onOverflowBottomEdge();
} else if (this.currentIndex < 0) {
this.onOverflowTopEdge(event);
this.onOverflowTopEdge();
}

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

this.update();
this.focusCurrent();
this.fireEvent(ItemNavigation.AFTER_FOCUS);
}

onkeydown(event) {
Expand All @@ -151,14 +139,6 @@ class ItemNavigation extends EventProvider {
if (isEnd(event)) {
return this._handleEnd(event);
}

if (isPageUp(event)) {
return this._handlePageUp(event);
}

if (isPageDown(event)) {
return this._handlePageDown(event);
}
}

_handleUp(event) {
Expand Down Expand Up @@ -205,20 +185,6 @@ class ItemNavigation extends EventProvider {
}
}

_handlePageUp(event) {
if (this._canNavigate()) {
this.currentIndex -= this.pageSize;
this._onKeyPress(event);
}
}

_handlePageDown(event) {
if (this._canNavigate()) {
this.currentIndex += this.pageSize;
this._onKeyPress(event);
}
}

/**
* Call this method to set a new "current" (selected) item in the item navigation
* Note: the item passed to this function must be one of the items, returned by the getItemsCallback function
Expand Down Expand Up @@ -323,71 +289,25 @@ class ItemNavigation extends EventProvider {

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

if (this.behavior === ItemNavigationBehavior.Cyclic) {
this.currentIndex = 0;
return;
}

if (this.behavior === ItemNavigationBehavior.Paging) {
this._handleNextPage();
} else {
this.currentIndex = items.length - 1;
}

this.fireEvent(ItemNavigation.BORDER_REACH, {
start: false,
end: true,
originalEvent: event,
offset,
});
this.currentIndex = items.length - 1;
}

onOverflowTopEdge(event) {
const items = this._getItems();
const offsetRight = (this.currentIndex + this.rowSize) % this.rowSize;
const offset = offsetRight < 0 ? (this.rowSize + offsetRight) : offsetRight;

if (this.behavior === ItemNavigationBehavior.Cyclic) {
this.currentIndex = items.length - 1;
return;
}

if (this.behavior === ItemNavigationBehavior.Paging) {
this._handlePrevPage();
} else {
this.currentIndex = 0;
}

this.fireEvent(ItemNavigation.BORDER_REACH, {
start: true,
end: false,
originalEvent: event,
offset,
});
}

_handleNextPage() {
const items = this._getItems();

if (!this._hasNextPage()) {
this.currentIndex = items.length - 1;
} else {
this.currentIndex -= this.pageSize;
}
}

_handlePrevPage() {
if (!this._hasPreviousPage()) {
this.currentIndex = 0;
} else {
this.currentIndex = this.pageSize + this.currentIndex;
}
this.currentIndex = 0;
}
}

ItemNavigation.BORDER_REACH = "_borderReach";
ItemNavigation.AFTER_FOCUS = "_afterFocus";

export default ItemNavigation;
25 changes: 24 additions & 1 deletion packages/base/src/delegate/ScrollEnablement.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,30 @@ class ScrollEnablement extends EventProvider {
return this._container;
}

scrollTo(left, top) {
/**
* Scrolls the container to the left/top position, retrying retryCount times, if the container is not yet painted
*
* @param left
* @param top
* @param retryCount
* @param retryInterval
* @returns {Promise<void>} resolved when scrolled successfully
*/
async scrollTo(left, top, retryCount = 0, retryInterval = 0) {
let containerPainted = this.scrollContainer.clientHeight > 0 && this.scrollContainer.clientWidth > 0;

/* eslint-disable no-loop-func, no-await-in-loop */
while (!containerPainted && retryCount > 0) {
await new Promise(resolve => {
setTimeout(() => {
containerPainted = this.scrollContainer.clientHeight > 0 && this.scrollContainer.clientWidth > 0;
retryCount--;
resolve();
}, retryInterval);
});
}
/* eslint-disable no-loop-func, no-await-in-loop */

this._container.scrollLeft = left;
this._container.scrollTop = top;
}
Expand Down
1 change: 1 addition & 0 deletions packages/base/src/features/browsersupport/IE11.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import "../../thirdparty/Object.entries.js";
// Array
import "../../thirdparty/Array.prototype.fill.js";
import "../../thirdparty/Array.prototype.find.js";
import "../../thirdparty/Array.prototype.findIndex.js";
import "../../thirdparty/Array.prototype.includes.js";

// Map
Expand Down
46 changes: 46 additions & 0 deletions packages/base/src/thirdparty/Array.prototype.findIndex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// https://tc39.github.io/ecma262/#sec-array.prototype.findindex
if (!Array.prototype.findIndex) {
Object.defineProperty(Array.prototype, 'findIndex', {
value: function(predicate) {
// 1. Let O be ? ToObject(this value).
if (this == null) {
throw new TypeError('"this" is null or not defined');
}

var o = Object(this);

// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;

// 3. If IsCallable(predicate) is false, throw a TypeError exception.
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}

// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.
var thisArg = arguments[1];

// 5. Let k be 0.
var k = 0;

// 6. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kValue be ? Get(O, Pk).
// c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).
// d. If testResult is true, return k.
var kValue = o[k];
if (predicate.call(thisArg, kValue, k, o)) {
return k;
}
// e. Increase k by 1.
k++;
}

// 7. Return -1.
return -1;
},
configurable: true,
writable: true
});
}
4 changes: 2 additions & 2 deletions packages/base/src/thirdparty/Element.prototype.closest.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
if (!Element.prototype.closest) {
Element.prototype.closest = function(s) {
var el = this;
if (!document.documentElement.contains(el)) return null;

do {
if (el.matches(s)) return el;
if (Element.prototype.matches.call(el, s)) return el;
el = el.parentElement || el.parentNode;
} while (el !== null && el.nodeType === 1);
return null;
Expand Down
17 changes: 0 additions & 17 deletions packages/base/src/types/CalendarSelection.js

This file was deleted.

9 changes: 2 additions & 7 deletions packages/base/src/types/ItemNavigationBehavior.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,13 @@
*/
const ItemNavigationBehavior = {
/**
* Static behavior: when border of the items is reached, you can't go out of the cage.
* Static behavior: navigations stops at the first or last item.
*/
Static: "Static",

/**
* Cycling behavior: when border of the items is reached, you can cycle through the items.
* Cycling behavior: navigating past the last item continues with the first and vice versa.
*/
Cyclic: "Cyclic",

/**
* Paging behavior: when border of the items is reached, tou can go up/down based on the rowsize(e.g. DayPicker)
*/
Paging: "Paging",
};
export default ItemNavigationBehavior;
Loading

0 comments on commit 3e684b4

Please sign in to comment.