Skip to content

Commit

Permalink
feat: implement F6 Navigation Helper (#4490)
Browse files Browse the repository at this point in the history
  • Loading branch information
fifoosid authored Jan 11, 2022
1 parent b646157 commit 60d0dc1
Show file tree
Hide file tree
Showing 28 changed files with 844 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ before_install:
- gem install jekyll-seo-tag

script:
- DEPLOY_PUBLIC_PATH=/resources/ yarn build
- DEPLOY_PUBLIC_PATH=/resources/ ENABLE_CLDR=1 yarn build
- yarn test

deploy:
Expand Down
2 changes: 1 addition & 1 deletion packages/base/hash.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
LwpwazozKyw2R4uvmZVLv5VZq7E=
35rcbBXTa7Q432kQnojY0s3empY=
45 changes: 30 additions & 15 deletions packages/base/src/Boot.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import applyTheme from "./theming/applyTheme.js";
import { registerCurrentRuntime } from "./Runtimes.js";
import { getFeature } from "./FeaturesRegistry.js";

let booted = false;
let bootPromise;
const eventProvider = new EventProvider();

/**
Expand All @@ -20,24 +20,39 @@ const attachBoot = listener => {
};

const boot = async () => {
if (booted) {
return;
if (bootPromise) {
return bootPromise;
}

registerCurrentRuntime();
/* eslint-disable no-alert, no-async-promise-executor */
/*
Note(since we disable eslint rule):
If an async executor function throws an error, the error will be lost and won't cause the newly-constructed Promise to reject.
This could make it difficult to debug and handle some errors.
*/
bootPromise = new Promise(async resolve => {
registerCurrentRuntime();

const OpenUI5Support = getFeature("OpenUI5Support");
if (OpenUI5Support) {
await OpenUI5Support.init();
}
const OpenUI5Support = getFeature("OpenUI5Support");
const F6Navigation = getFeature("F6Navigation");
if (OpenUI5Support) {
await OpenUI5Support.init();
} else if (F6Navigation) {
F6Navigation.init();
}

await whenDOMReady();
await applyTheme(getTheme());
OpenUI5Support && OpenUI5Support.attachListeners();
insertFontFace();
insertSystemCSSVars();
await eventProvider.fireEventAsync("boot");

resolve();
});
/* eslint-enable no-alert, no-async-promise-executor */

await whenDOMReady();
await applyTheme(getTheme());
OpenUI5Support && OpenUI5Support.attachListeners();
insertFontFace();
insertSystemCSSVars();
await eventProvider.fireEventAsync("boot");
booted = true;
return bootPromise;
};

export {
Expand Down
5 changes: 4 additions & 1 deletion packages/base/src/FeaturesRegistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ const getFeature = name => {
return features.get(name);
};

export { registerFeature, getFeature };
export {
registerFeature,
getFeature,
};
8 changes: 8 additions & 0 deletions packages/base/src/Keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ const isF4 = event => {

const isF4Shift = event => (event.key ? event.key === "F4" : event.keyCode === KeyCodes.F4) && checkModifierKeys(event, false, false, true);

const isF6Next = event => ((event.key ? event.key === "F6" : event.keyCode === KeyCodes.F6) && checkModifierKeys(event, false, false, false))
|| ((event.key ? (event.key === "ArrowDown" || event.key === "Down") : event.keyCode === KeyCodes.ARROW_DOWN) && checkModifierKeys(event, true, true, false));

const isF6Previous = event => ((event.key ? event.key === "F6" : event.keyCode === KeyCodes.F6) && checkModifierKeys(event, false, false, true))
|| ((event.key ? (event.key === "ArrowUp" || event.key === "Up") : event.keyCode === KeyCodes.ARROW_Up) && checkModifierKeys(event, true, true, false));

const isF7 = event => (event.key ? event.key === "F7" : event.keyCode === KeyCodes.F7) && !hasModifierKeys(event);

const isShowByArrows = event => {
Expand Down Expand Up @@ -236,6 +242,8 @@ export {
isShow,
isF4,
isF4Shift,
isF6Previous,
isF6Next,
isF7,
isPageUp,
isPageDown,
Expand Down
3 changes: 3 additions & 0 deletions packages/base/src/UI5Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ class UI5Element extends HTMLElement {
*/
async connectedCallback() {
this.setAttribute(this.constructor.getMetadata().getPureTag(), "");
if (this.constructor.getMetadata().supportsF6FastNavigation()) {
this.setAttribute("data-sap-ui-fastnavgroup", "true");
}

const slotsAreManaged = this.constructor.getMetadata().slotsAreManaged();

Expand Down
8 changes: 8 additions & 0 deletions packages/base/src/UI5ElementMetadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,14 @@ class UI5ElementMetadata {
return !!this.metadata.managedSlots;
}

/**
* Determines whether this control supports F6 fast navigation
* @public
*/
supportsF6FastNavigation() {
return !!this.metadata.fastNavigation;
}

/**
* Returns an object with key-value pairs of properties and their metadata definitions
* @public
Expand Down
14 changes: 8 additions & 6 deletions packages/base/src/util/FocusableElements.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,38 @@ const isFocusTrap = el => {
return el.hasAttribute("data-ui5-focus-trap");
};

const getFirstFocusableElement = async container => {
const getFirstFocusableElement = async (container, startFromContainer) => {
if (!container || isNodeHidden(container)) {
return null;
}

return findFocusableElement(container, true);
return findFocusableElement(container, true, startFromContainer);
};

const getLastFocusableElement = async container => {
const getLastFocusableElement = async (container, startFromContainer) => {
if (!container || isNodeHidden(container)) {
return null;
}

return findFocusableElement(container, false);
return findFocusableElement(container, false, startFromContainer);
};

const isElemFocusable = el => {
return el.hasAttribute("data-ui5-focus-redirect") || !isNodeHidden(el);
};

const findFocusableElement = async (container, forward) => {
const findFocusableElement = async (container, forward, startFromContainer) => {
let child;

if (container.shadowRoot) {
child = forward ? container.shadowRoot.firstChild : container.shadowRoot.lastChild;
} else if (container.assignedNodes && container.assignedNodes()) {
const assignedElements = container.assignedNodes();
child = forward ? assignedElements[0] : assignedElements[assignedElements.length - 1];
} else if (startFromContainer) {
child = container;
} else {
child = forward ? container.firstChild : container.lastChild;
child = forward ? container.firstElementChild : container.lastElementChild;
}

let focusableDescendant;
Expand Down
2 changes: 1 addition & 1 deletion packages/base/src/util/isNodeHidden.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const isNodeHidden = node => {
return false;
}

return (node.offsetWidth <= 0 && node.offsetHeight <= 0) || node.style.visibility === "hidden";
return (node.offsetWidth <= 0 && node.offsetHeight <= 0) || (node.style && node.style.visibility === "hidden");
};

export default isNodeHidden;
1 change: 1 addition & 0 deletions packages/fiori/src/Bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import BarCss from "./generated/themes/Bar.css.js";
const metadata = {
tag: "ui5-bar",
managedSlots: true,
fastNavigation: true,
properties: /** @lends sap.ui.webcomponents.fiori.Bar.prototype */ {
/**
* Defines the <code>ui5-bar</code> design.
Expand Down
1 change: 1 addition & 0 deletions packages/fiori/src/FlexibleColumnLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import FlexibleColumnLayoutCss from "./generated/themes/FlexibleColumnLayout.css
*/
const metadata = {
tag: "ui5-flexible-column-layout",
fastNavigation: true,
properties: /** @lends sap.ui.webcomponents.fiori.FlexibleColumnLayout.prototype */ {
/**
* Defines the columns layout and their proportion.
Expand Down
1 change: 1 addition & 0 deletions packages/fiori/src/ShellBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const HANDLE_RESIZE_DEBOUNCE_RATE = 200; // ms
const metadata = {
tag: "ui5-shellbar",
languageAware: true,
fastNavigation: true,
properties: /** @lends sap.ui.webcomponents.fiori.ShellBar.prototype */ {

/**
Expand Down
1 change: 1 addition & 0 deletions packages/fiori/src/SideNavigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import SideNavigationPopoverCss from "./generated/themes/SideNavigationPopover.c
const metadata = {
tag: "ui5-side-navigation",
managedSlots: true,
fastNavigation: true,
properties: /** @lends sap.ui.webcomponents.fiori.SideNavigation.prototype */ {
/**
* Defines whether the <code>ui5-side-navigation</code> is expanded or collapsed.
Expand Down
1 change: 1 addition & 0 deletions packages/fiori/src/Wizard.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const STEP_SWITCH_THRESHOLDS = {
const metadata = {
tag: "ui5-wizard",
managedSlots: true,
fastNavigation: true,
properties: /** @lends sap.ui.webcomponents.fiori.Wizard.prototype */ {
/**
* Defines the width of the <code>ui5-wizard</code>.
Expand Down
Loading

0 comments on commit 60d0dc1

Please sign in to comment.