@furo/util
Version:
206 lines (174 loc) • 6.49 kB
JavaScript
import { LitElement, css } from 'lit';
import { FBP } from '@furo/fbp';
/**
* `furo-navigation-pad` listens to different keyboard navigation events like the arrow keys. It will attach the listeners
* to the parent node and cancel the default and stop the propagation of the events.
*
* The events are available as standalone events or as combined event in the `navigated` event.
*
* ```html
* <!-- forward all navigation events except the Escape -->
* <furo-navigation-pad
* ignored-keys="Escape" at-navigated="--navpad"
* ></furo-navigation-pad>
*
* ```
*
*
* @fires {String} navigated - Generic navigation event, fired when one of the navigation keys was pressed, detail contains
* one of these: Escape | Enter | ArrowDown | ArrowUp |ArrowLeft|ArrowRight| PageUp | PageDown | Home | End
* @fires {KeyboardEvent} enter-pressed - Fired when Enter key was pressed.
* @fires {KeyboardEvent} arrow-down-pressed - Fired when ArrowDown key was pressed.
* @fires {KeyboardEvent} arrow-up-pressed - Fired when ArrowUp key was pressed.
* @fires {KeyboardEvent} arrow-left-pressed - Fired when ArrowLeft key was pressed.
* @fires {KeyboardEvent} arrow-right-pressed - Fired when ArrowRight key was pressed.
* @fires {KeyboardEvent} escape-pressed - Fired when Escape key was pressed.
* @fires {KeyboardEvent} page-up-pressed - Fired when PageUp key was pressed.
* @fires {KeyboardEvent} page-down-pressed - Fired when PageDown key was pressed.
* @fires {KeyboardEvent} home-pressed - Fired when Home key was pressed.
* @fires {KeyboardEvent} end-pressed - Fired when End key was pressed.
*
*
* @summary keyboard navigation helper
* @customElement
* @appliesMixin FBP
*/
export class FuroNavigationPad extends FBP(LitElement) {
/**
* @private
* @return {Object}
*/
static get properties() {
return {
/**
* Enter the keys you want to ignore as comma seperated values.
*
* i.e. "Escape, ArrowLeft"
*
* @type String
*/
ignoredKeys: { type: String, attribute: 'ignored-keys' },
};
}
/**
* flow is ready lifecycle method
* @private
*/
_FBPReady() {
super._FBPReady();
// this._FBPTraceWires()
this.parentNode.addEventListener('keydown', event => {
const key = event.key || event.keyCode;
// abort on modifier keys
if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey) {
return;
}
// abort on ignoredKeys
if (
this.ignoredKeys &&
this.ignoredKeys.split(',').filter(k => k.trim() === key).length > 0
) {
return;
}
const navigatedEvent = new Event('navigated', { composed: true, bubbles: true });
navigatedEvent.initiatorEvent = event;
const enterEvent = new Event('enter-pressed', { composed: true, bubbles: true });
const arrowDownEvent = new Event('arrow-down-pressed', { composed: true, bubbles: true });
const arrowUpEvent = new Event('arrow-up-pressed', { composed: true, bubbles: true });
const endEvent = new Event('end-pressed', { composed: true, bubbles: true });
const homeEvent = new Event('home-pressed', { composed: true, bubbles: true });
const pageDownEvent = new Event('page-down-pressed', { composed: true, bubbles: true });
const pageUpEvent = new Event('page-up-pressed', { composed: true, bubbles: true });
const escapeEvent = new Event('escape-pressed', { composed: true, bubbles: true });
const arrowLeftEvent = new Event('arrow-left-pressed', { composed: true, bubbles: true });
const arrowRightEvent = new Event('arrow-right-pressed', { composed: true, bubbles: true });
switch (key) {
case 'Enter':
event.stopPropagation();
navigatedEvent.detail = key;
this.dispatchEvent(navigatedEvent);
enterEvent.detail = event;
this.dispatchEvent(enterEvent);
break;
case 'ArrowDown':
event.stopPropagation();
navigatedEvent.detail = key;
this.dispatchEvent(navigatedEvent);
arrowDownEvent.detail = event;
this.dispatchEvent(arrowDownEvent);
break;
case 'ArrowUp':
event.stopPropagation();
navigatedEvent.detail = key;
this.dispatchEvent(navigatedEvent);
arrowUpEvent.detail = event;
this.dispatchEvent(arrowUpEvent);
break;
case 'ArrowLeft':
event.stopPropagation();
navigatedEvent.detail = key;
this.dispatchEvent(navigatedEvent);
arrowLeftEvent.detail = event;
this.dispatchEvent(arrowLeftEvent);
break;
case 'ArrowRight':
event.stopPropagation();
navigatedEvent.detail = key;
this.dispatchEvent(navigatedEvent);
arrowRightEvent.detail = event;
this.dispatchEvent(arrowRightEvent);
break;
case 'Escape':
event.stopPropagation();
navigatedEvent.detail = key;
this.dispatchEvent(navigatedEvent);
escapeEvent.detail = event;
this.dispatchEvent(escapeEvent);
break;
case 'PageUp':
event.stopPropagation();
navigatedEvent.detail = key;
this.dispatchEvent(navigatedEvent);
pageUpEvent.detail = event;
this.dispatchEvent(pageUpEvent);
break;
case 'PageDown':
event.stopPropagation();
navigatedEvent.detail = key;
this.dispatchEvent(navigatedEvent);
pageDownEvent.detail = event;
this.dispatchEvent(pageDownEvent);
break;
case 'Home':
event.stopPropagation();
navigatedEvent.detail = key;
this.dispatchEvent(navigatedEvent);
homeEvent.detail = event;
this.dispatchEvent(homeEvent);
break;
case 'End':
event.stopPropagation();
navigatedEvent.detail = key;
this.dispatchEvent(navigatedEvent);
endEvent.detail = event;
this.dispatchEvent(endEvent);
break;
default:
}
});
}
/**
* Themable Styles
* @private
* @return {CSSResult}
*/
static get styles() {
// language=CSS
return css`
:host {
display: none;
}
`;
}
}
window.customElements.define('furo-navigation-pad', FuroNavigationPad);