diff --git a/packages/mdc-ripple/foundation.js b/packages/mdc-ripple/foundation.js index f5c510cf5e2..0b4d1c89e25 100644 --- a/packages/mdc-ripple/foundation.js +++ b/packages/mdc-ripple/foundation.js @@ -28,6 +28,8 @@ const DEACTIVATION_ACTIVATION_PAIRS = { blur: 'focus', }; +const DEACTIVATION_TIMEOUT = 200; + export default class MDCRippleFoundation extends MDCFoundation { static get cssClasses() { return cssClasses; @@ -152,6 +154,7 @@ export default class MDCRippleFoundation extends MDCFoundation { ); activationState.activationStartTime = Date.now(); + this.deactivateOnHold_(e); requestAnimationFrame(() => { // This needs to be wrapped in an rAF call b/c web browsers // report active states inconsistently when they're called within @@ -203,6 +206,42 @@ export default class MDCRippleFoundation extends MDCFoundation { this.adapter_.addClass(FG_UNBOUNDED_ACTIVATION); } + deactivateOnHold_(e) { + const {activationState_: activationState} = this; + + if (e === null || activationState.isProgrammatic) { + return; + } + + // Ripple gets deactivated on hold + if (Date.now() - activationState.activationStartTime > DEACTIVATION_TIMEOUT) { + // Shallow event cloning + const newEvent = {}; + + for (const key in e) { + if (e[key] !== null) { + newEvent[key] = e[key]; + } + } + + // Reversing activation/event types + for (const key in DEACTIVATION_ACTIVATION_PAIRS) { + if (DEACTIVATION_ACTIVATION_PAIRS[key] === e.type) { + newEvent.type = key; + break; + } + } + + this.deactivate_(newEvent); + activationState.isActivated = false; + return; + } + + requestAnimationFrame(() => { + this.deactivateOnHold_(e); + }); + } + deactivate_(e) { const {activationState_: activationState} = this; // This can happen in scenarios such as when you have a keyup event that blurs the element.