UNPKG

@logo-elements/component-base

Version:

A set of mixins used by Logo Elements which is extended from Vaadin components.

119 lines (105 loc) 3.31 kB
/** * @license * Copyright LOGO YAZILIM SANAYİ VE TİCARET A.Ş. * * Save to the extent permitted by law, you may not use, copy, modify, * distribute or create derivative works of this material or any part * of it without the prior written consent of LOGO YAZILIM SANAYİ VE TİCARET A.Ş. Limited. * Any reproduction of this material must contain this notice. */ import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin.js'; // We consider the keyboard to be active if the window has received a keydown // event since the last mousedown event. let keyboardActive = false; // Listen for top-level keydown and mousedown events. // Use capture phase so we detect events even if they're handled. window.addEventListener( 'keydown', () => { keyboardActive = true; }, { capture: true } ); window.addEventListener( 'mousedown', () => { keyboardActive = false; }, { capture: true } ); /** * A mixin to handle `focused` and `focus-ring` attributes based on focus. * * @polymerMixin */ export const FocusMixin = dedupingMixin( (superclass) => class FocusMixinClass extends superclass { /** * @protected * @return {boolean} */ get _keyboardActive() { return keyboardActive; } /** @protected */ ready() { this.addEventListener('focusin', (e) => { if (this._shouldSetFocus(e)) { this._setFocused(true); } }); this.addEventListener('focusout', (e) => { if (this._shouldRemoveFocus(e)) { this._setFocused(false); } }); // In super.ready() other 'focusin' and 'focusout' listeners might be // added, so we call it after our own ones to ensure they execute first. // Issue to watch out: when incorrect, <logo-elements-combo-box> refocuses the // input field on iOS after “Done” is pressed. super.ready(); } /** @protected */ disconnectedCallback() { super.disconnectedCallback(); // in non-Chrome browsers, blur does not fire on the element when it is disconnected. // reproducible in `<logo-elements-date-picker>` when closing on `Cancel` or `Today` click. if (this.hasAttribute('focused')) { this._setFocused(false); } } /** * Override to change how focused and focus-ring attributes are set. * * @param {boolean} focused * @protected */ _setFocused(focused) { this.toggleAttribute('focused', focused); // focus-ring is true when the element was focused from the keyboard. // Focus Ring [A11ycasts]: https://youtu.be/ilj2P5-5CjI this.toggleAttribute('focus-ring', focused && this._keyboardActive); } /** * Override to define if the field receives focus based on the event. * * @param {FocusEvent} _event * @return {boolean} * @protected */ _shouldSetFocus(_event) { return true; } /** * Override to define if the field loses focus based on the event. * * @param {FocusEvent} _event * @return {boolean} * @protected */ _shouldRemoveFocus(_event) { return true; } } );