@material/ripple
Advanced tools
Comparing version 0.29.0 to 0.30.0
@@ -60,2 +60,5 @@ /** | ||
/** @param {!EventTarget} target */ | ||
containsEventTarget(target) {} | ||
/** | ||
@@ -62,0 +65,0 @@ * @param {string} evtType |
@@ -78,3 +78,3 @@ /*! | ||
/******/ // Load entry module and return exports | ||
/******/ return __webpack_require__(__webpack_require__.s = 87); | ||
/******/ return __webpack_require__(__webpack_require__.s = 99); | ||
/******/ }) | ||
@@ -607,2 +607,8 @@ /************************************************************************/ | ||
/** @param {!EventTarget} target */ | ||
}, { | ||
key: "containsEventTarget", | ||
value: function containsEventTarget(target) {} | ||
/** | ||
@@ -689,3 +695,3 @@ * @param {string} evtType | ||
/***/ 5: | ||
/***/ 4: | ||
/***/ (function(module, __webpack_exports__, __webpack_require__) { | ||
@@ -868,2 +874,5 @@ | ||
}, | ||
containsEventTarget: function containsEventTarget(target) { | ||
return instance.root_.contains(target); | ||
}, | ||
registerInteractionHandler: function registerInteractionHandler(evtType, handler) { | ||
@@ -1021,2 +1030,6 @@ return instance.root_.addEventListener(evtType, handler, __WEBPACK_IMPORTED_MODULE_3__util__["applyPassive"]()); | ||
// Tracks activations that have occurred on the current frame, to avoid simultaneous nested activations | ||
/** @type {!Array<!EventTarget>} */ | ||
var activatedTargets = []; | ||
/** | ||
@@ -1054,2 +1067,3 @@ * @extends {MDCFoundation<!MDCRippleAdapter>} | ||
removeClass: function removeClass() /* className: string */{}, | ||
containsEventTarget: function containsEventTarget() /* target: !EventTarget */{}, | ||
registerInteractionHandler: function registerInteractionHandler() /* evtType: string, handler: EventListener */{}, | ||
@@ -1083,5 +1097,2 @@ deregisterInteractionHandler: function deregisterInteractionHandler() /* evtType: string, handler: EventListener */{}, | ||
/** @private {number} */ | ||
_this.xfDuration_ = 0; | ||
/** @private {number} */ | ||
_this.initialSize_ = 0; | ||
@@ -1319,3 +1330,2 @@ | ||
var activationState = this.activationState_; | ||
if (activationState.isActivated) { | ||
@@ -1337,3 +1347,13 @@ return; | ||
var hasActivatedChild = e && activatedTargets.length > 0 && activatedTargets.some(function (target) { | ||
return _this9.adapter_.containsEventTarget(target); | ||
}); | ||
if (hasActivatedChild) { | ||
// Immediately reset activation state, while preserving logic that prevents touch follow-on events | ||
this.resetActivationState_(); | ||
return; | ||
} | ||
if (e) { | ||
activatedTargets.push( /** @type {!EventTarget} */e.target); | ||
this.registerDeactivationHandlers_(e); | ||
@@ -1355,2 +1375,5 @@ } | ||
} | ||
// Reset array on next frame after the current event has had a chance to bubble to prevent ancestor ripples | ||
activatedTargets = []; | ||
}); | ||
@@ -1423,5 +1446,5 @@ } | ||
value: function getFgTranslationCoordinates_() { | ||
var activationState = this.activationState_; | ||
var activationEvent = activationState.activationEvent, | ||
wasActivatedByPointer = activationState.wasActivatedByPointer; | ||
var _activationState_ = this.activationState_, | ||
activationEvent = _activationState_.activationEvent, | ||
wasActivatedByPointer = _activationState_.wasActivatedByPointer; | ||
@@ -1463,5 +1486,5 @@ | ||
var FG_DEACTIVATION = MDCRippleFoundation.cssClasses.FG_DEACTIVATION; | ||
var _activationState_ = this.activationState_, | ||
hasDeactivationUXRun = _activationState_.hasDeactivationUXRun, | ||
isActivated = _activationState_.isActivated; | ||
var _activationState_2 = this.activationState_, | ||
hasDeactivationUXRun = _activationState_2.hasDeactivationUXRun, | ||
isActivated = _activationState_2.isActivated; | ||
@@ -1585,14 +1608,24 @@ var activationHasEnded = hasDeactivationUXRun || !isActivated; | ||
value: function layoutInternal_() { | ||
var _this15 = this; | ||
this.frame_ = this.adapter_.computeBoundingRect(); | ||
var maxDim = Math.max(this.frame_.height, this.frame_.width); | ||
var surfaceDiameter = Math.sqrt(Math.pow(this.frame_.width, 2) + Math.pow(this.frame_.height, 2)); | ||
// 60% of the largest dimension of the surface | ||
// Surface diameter is treated differently for unbounded vs. bounded ripples. | ||
// Unbounded ripple diameter is calculated smaller since the surface is expected to already be padded appropriately | ||
// to extend the hitbox, and the ripple is expected to meet the edges of the padded hitbox (which is typically | ||
// square). Bounded ripples, on the other hand, are fully expected to expand beyond the surface's longest diameter | ||
// (calculated based on the diagonal plus a constant padding), and are clipped at the surface's border via | ||
// `overflow: hidden`. | ||
var getBoundedRadius = function getBoundedRadius() { | ||
var hypotenuse = Math.sqrt(Math.pow(_this15.frame_.width, 2) + Math.pow(_this15.frame_.height, 2)); | ||
return hypotenuse + MDCRippleFoundation.numbers.PADDING; | ||
}; | ||
this.maxRadius_ = this.adapter_.isUnbounded() ? maxDim : getBoundedRadius(); | ||
// Ripple is sized as a fraction of the largest dimension of the surface, then scales up using a CSS scale transform | ||
this.initialSize_ = maxDim * MDCRippleFoundation.numbers.INITIAL_ORIGIN_SCALE; | ||
this.fgScale_ = this.maxRadius_ / this.initialSize_; | ||
// Diameter of the surface + 10px | ||
this.maxRadius_ = surfaceDiameter + MDCRippleFoundation.numbers.PADDING; | ||
this.fgScale_ = this.maxRadius_ / this.initialSize_; | ||
this.xfDuration_ = 1000 * Math.sqrt(this.maxRadius_ / 1024); | ||
this.updateLayoutCssVars_(); | ||
@@ -1704,6 +1737,6 @@ } | ||
/***/ 87: | ||
/***/ 99: | ||
/***/ (function(module, exports, __webpack_require__) { | ||
module.exports = __webpack_require__(5); | ||
module.exports = __webpack_require__(4); | ||
@@ -1714,2 +1747,3 @@ | ||
/******/ }); | ||
}); | ||
}); | ||
//# sourceMappingURL=mdc.ripple.js.map |
@@ -6,3 +6,3 @@ /*! | ||
*/ | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ripple=e():(t.mdc=t.mdc||{},t.mdc.ripple=e())}(this,function(){return function(t){function e(i){if(n[i])return n[i].exports;var a=n[i]={i:i,l:!1,exports:{}};return t[i].call(a.exports,a,a.exports,e),a.l=!0,a.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,i){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:i})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="/assets/",e(e.s=87)}({0:function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var a=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}(),r=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};i(this,t),this.adapter_=e}return a(t,null,[{key:"cssClasses",get:function(){return{}}},{key:"strings",get:function(){return{}}},{key:"numbers",get:function(){return{}}},{key:"defaultAdapter",get:function(){return{}}}]),a(t,[{key:"init",value:function(){}},{key:"destroy",value:function(){}}]),t}();e.a=r},1:function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var a=n(0),r=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}(),o=function(){function t(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;i(this,t),this.root_=e;for(var a=arguments.length,r=Array(a>2?a-2:0),o=2;o<a;o++)r[o-2]=arguments[o];this.initialize.apply(this,r),this.foundation_=void 0===n?this.getDefaultFoundation():n,this.foundation_.init(),this.initialSyncWithDOM()}return r(t,null,[{key:"attachTo",value:function(e){return new t(e,new a.a)}}]),r(t,[{key:"initialize",value:function(){}},{key:"getDefaultFoundation",value:function(){throw new Error("Subclasses must override getDefaultFoundation to return a properly configured foundation class")}},{key:"initialSyncWithDOM",value:function(){}},{key:"destroy",value:function(){this.foundation_.destroy()}},{key:"listen",value:function(t,e){this.root_.addEventListener(t,e)}},{key:"unlisten",value:function(t,e){this.root_.removeEventListener(t,e)}},{key:"emit",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=void 0;"function"==typeof CustomEvent?i=new CustomEvent(t,{detail:e,bubbles:n}):(i=document.createEvent("CustomEvent"),i.initCustomEvent(t,n,!1,e)),this.root_.dispatchEvent(i)}}]),t}();e.a=o},2:function(t,e,n){"use strict";function i(t){var e=t.document,n=e.createElement("div");n.className="mdc-ripple-surface--test-edge-var-bug",e.body.appendChild(n);var i=t.getComputedStyle(n),a=null!==i&&"solid"===i.borderTopStyle;return n.remove(),a}function a(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if("boolean"==typeof u&&!e)return u;if(t.CSS&&"function"==typeof t.CSS.supports){var n=t.CSS.supports("--css-vars","yes"),a=t.CSS.supports("(--css-vars: yes)")&&t.CSS.supports("color","#00000000");return u=!(!n&&!a||i(t))}}function r(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:window,e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(void 0===c||e){var n=!1;try{t.document.addEventListener("test",null,{get passive(){n=!0}})}catch(t){}c=n}return!!c&&{passive:!0}}function o(t){return["webkitMatchesSelector","msMatchesSelector","matches"].filter(function(e){return e in t}).pop()}function s(t,e,n){var i=e.x,a=e.y,r=i+n.left,o=a+n.top,s=void 0,u=void 0;return"touchstart"===t.type?(s=t.changedTouches[0].pageX-r,u=t.changedTouches[0].pageY-o):(s=t.pageX-r,u=t.pageY-o),{x:s,y:u}}Object.defineProperty(e,"__esModule",{value:!0}),n.d(e,"supportsCssVariables",function(){return a}),n.d(e,"applyPassive",function(){return r}),n.d(e,"getMatchesProperty",function(){return o}),n.d(e,"getNormalizedEventCoords",function(){return s});/** | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ripple=e():(t.mdc=t.mdc||{},t.mdc.ripple=e())}(this,function(){return function(t){function e(i){if(n[i])return n[i].exports;var a=n[i]={i:i,l:!1,exports:{}};return t[i].call(a.exports,a,a.exports,e),a.l=!0,a.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,i){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:i})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="/assets/",e(e.s=99)}({0:function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var a=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}(),r=function(){function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};i(this,t),this.adapter_=e}return a(t,null,[{key:"cssClasses",get:function(){return{}}},{key:"strings",get:function(){return{}}},{key:"numbers",get:function(){return{}}},{key:"defaultAdapter",get:function(){return{}}}]),a(t,[{key:"init",value:function(){}},{key:"destroy",value:function(){}}]),t}();e.a=r},1:function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var a=n(0),r=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}(),o=function(){function t(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:void 0;i(this,t),this.root_=e;for(var a=arguments.length,r=Array(a>2?a-2:0),o=2;o<a;o++)r[o-2]=arguments[o];this.initialize.apply(this,r),this.foundation_=void 0===n?this.getDefaultFoundation():n,this.foundation_.init(),this.initialSyncWithDOM()}return r(t,null,[{key:"attachTo",value:function(e){return new t(e,new a.a)}}]),r(t,[{key:"initialize",value:function(){}},{key:"getDefaultFoundation",value:function(){throw new Error("Subclasses must override getDefaultFoundation to return a properly configured foundation class")}},{key:"initialSyncWithDOM",value:function(){}},{key:"destroy",value:function(){this.foundation_.destroy()}},{key:"listen",value:function(t,e){this.root_.addEventListener(t,e)}},{key:"unlisten",value:function(t,e){this.root_.removeEventListener(t,e)}},{key:"emit",value:function(t,e){var n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],i=void 0;"function"==typeof CustomEvent?i=new CustomEvent(t,{detail:e,bubbles:n}):(i=document.createEvent("CustomEvent"),i.initCustomEvent(t,n,!1,e)),this.root_.dispatchEvent(i)}}]),t}();e.a=o},2:function(t,e,n){"use strict";function i(t){var e=t.document,n=e.createElement("div");n.className="mdc-ripple-surface--test-edge-var-bug",e.body.appendChild(n);var i=t.getComputedStyle(n),a=null!==i&&"solid"===i.borderTopStyle;return n.remove(),a}function a(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if("boolean"==typeof u&&!e)return u;if(t.CSS&&"function"==typeof t.CSS.supports){var n=t.CSS.supports("--css-vars","yes"),a=t.CSS.supports("(--css-vars: yes)")&&t.CSS.supports("color","#00000000");return u=!(!n&&!a||i(t))}}function r(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:window,e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(void 0===c||e){var n=!1;try{t.document.addEventListener("test",null,{get passive(){n=!0}})}catch(t){}c=n}return!!c&&{passive:!0}}function o(t){return["webkitMatchesSelector","msMatchesSelector","matches"].filter(function(e){return e in t}).pop()}function s(t,e,n){var i=e.x,a=e.y,r=i+n.left,o=a+n.top,s=void 0,u=void 0;return"touchstart"===t.type?(s=t.changedTouches[0].pageX-r,u=t.changedTouches[0].pageY-o):(s=t.pageX-r,u=t.pageY-o),{x:s,y:u}}Object.defineProperty(e,"__esModule",{value:!0}),n.d(e,"supportsCssVariables",function(){return a}),n.d(e,"applyPassive",function(){return r}),n.d(e,"getMatchesProperty",function(){return o}),n.d(e,"getNormalizedEventCoords",function(){return s});/** | ||
* @license | ||
@@ -23,3 +23,3 @@ * Copyright 2016 Google Inc. All Rights Reserved. | ||
*/ | ||
var u=void 0,c=void 0},3:function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var a=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}();!function(){function t(){i(this,t)}a(t,[{key:"browserSupportsCssVars",value:function(){}},{key:"isUnbounded",value:function(){}},{key:"isSurfaceActive",value:function(){}},{key:"isSurfaceDisabled",value:function(){}},{key:"addClass",value:function(t){}},{key:"removeClass",value:function(t){}},{key:"registerInteractionHandler",value:function(t,e){}},{key:"deregisterInteractionHandler",value:function(t,e){}},{key:"registerDocumentInteractionHandler",value:function(t,e){}},{key:"deregisterDocumentInteractionHandler",value:function(t,e){}},{key:"registerResizeHandler",value:function(t){}},{key:"deregisterResizeHandler",value:function(t){}},{key:"updateCssVariable",value:function(t,e){}},{key:"computeBoundingRect",value:function(){}},{key:"getWindowPageOffset",value:function(){}}])}()},5:function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function r(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}Object.defineProperty(e,"__esModule",{value:!0}),n.d(e,"MDCRipple",function(){return d}),n.d(e,"RippleCapableSurface",function(){return l});var o=n(1),s=(n(3),n(6)),u=n(2);n.d(e,"MDCRippleFoundation",function(){return s.a}),n.d(e,"util",function(){return u});var c=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}(),d=function(t){function e(){var t;i(this,e);for(var n=arguments.length,r=Array(n),o=0;o<n;o++)r[o]=arguments[o];var s=a(this,(t=e.__proto__||Object.getPrototypeOf(e)).call.apply(t,[this].concat(r)));return s.disabled=!1,s.unbounded_,s}return r(e,t),c(e,[{key:"setUnbounded_",value:function(){this.foundation_.setUnbounded(this.unbounded_)}},{key:"activate",value:function(){this.foundation_.activate()}},{key:"deactivate",value:function(){this.foundation_.deactivate()}},{key:"layout",value:function(){this.foundation_.layout()}},{key:"getDefaultFoundation",value:function(){return new s.a(e.createAdapter(this))}},{key:"initialSyncWithDOM",value:function(){this.unbounded="mdcRippleIsUnbounded"in this.root_.dataset}},{key:"unbounded",get:function(){return this.unbounded_},set:function(t){this.unbounded_=Boolean(t),this.setUnbounded_()}}],[{key:"attachTo",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=n.isUnbounded,a=void 0===i?void 0:i,r=new e(t);return void 0!==a&&(r.unbounded=a),r}},{key:"createAdapter",value:function(t){var e=u.getMatchesProperty(HTMLElement.prototype);return{browserSupportsCssVars:function(){return u.supportsCssVariables(window)},isUnbounded:function(){return t.unbounded},isSurfaceActive:function(){return t.root_[e](":active")},isSurfaceDisabled:function(){return t.disabled},addClass:function(e){return t.root_.classList.add(e)},removeClass:function(e){return t.root_.classList.remove(e)},registerInteractionHandler:function(e,n){return t.root_.addEventListener(e,n,u.applyPassive())},deregisterInteractionHandler:function(e,n){return t.root_.removeEventListener(e,n,u.applyPassive())},registerDocumentInteractionHandler:function(t,e){return document.documentElement.addEventListener(t,e,u.applyPassive())},deregisterDocumentInteractionHandler:function(t,e){return document.documentElement.removeEventListener(t,e,u.applyPassive())},registerResizeHandler:function(t){return window.addEventListener("resize",t)},deregisterResizeHandler:function(t){return window.removeEventListener("resize",t)},updateCssVariable:function(e,n){return t.root_.style.setProperty(e,n)},computeBoundingRect:function(){return t.root_.getBoundingClientRect()},getWindowPageOffset:function(){return{x:window.pageXOffset,y:window.pageYOffset}}}}}]),e}(o.a),l=function t(){i(this,t)};l.prototype.root_,l.prototype.unbounded,l.prototype.disabled},6:function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function r(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var o=n(0),s=(n(3),n(7)),u=n(2),c=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var i in n)Object.prototype.hasOwnProperty.call(n,i)&&(t[i]=n[i])}return t},d=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}(),l=["touchstart","pointerdown","mousedown","keydown"],f=["touchend","pointerup","mouseup"],v=function(t){function e(t){i(this,e);var n=a(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,c(e.defaultAdapter,t)));return n.layoutFrame_=0,n.frame_={width:0,height:0},n.activationState_=n.defaultActivationState_(),n.xfDuration_=0,n.initialSize_=0,n.maxRadius_=0,n.activateHandler_=function(t){return n.activate_(t)},n.deactivateHandler_=function(t){return n.deactivate_(t)},n.focusHandler_=function(){return requestAnimationFrame(function(){return n.adapter_.addClass(e.cssClasses.BG_FOCUSED)})},n.blurHandler_=function(){return requestAnimationFrame(function(){return n.adapter_.removeClass(e.cssClasses.BG_FOCUSED)})},n.resizeHandler_=function(){return n.layout()},n.unboundedCoords_={left:0,top:0},n.fgScale_=0,n.activationTimer_=0,n.fgDeactivationRemovalTimer_=0,n.activationAnimationHasEnded_=!1,n.activationTimerCallback_=function(){n.activationAnimationHasEnded_=!0,n.runDeactivationUXLogicIfReady_()},n.previousActivationEvent_=null,n}return r(e,t),d(e,null,[{key:"cssClasses",get:function(){return s.a}},{key:"strings",get:function(){return s.c}},{key:"numbers",get:function(){return s.b}},{key:"defaultAdapter",get:function(){return{browserSupportsCssVars:function(){},isUnbounded:function(){},isSurfaceActive:function(){},isSurfaceDisabled:function(){},addClass:function(){},removeClass:function(){},registerInteractionHandler:function(){},deregisterInteractionHandler:function(){},registerDocumentInteractionHandler:function(){},deregisterDocumentInteractionHandler:function(){},registerResizeHandler:function(){},deregisterResizeHandler:function(){},updateCssVariable:function(){},computeBoundingRect:function(){},getWindowPageOffset:function(){}}}}]),d(e,[{key:"isSupported_",value:function(){return this.adapter_.browserSupportsCssVars()}},{key:"defaultActivationState_",value:function(){return{isActivated:!1,hasDeactivationUXRun:!1,wasActivatedByPointer:!1,wasElementMadeActive:!1,activationEvent:null,isProgrammatic:!1}}},{key:"init",value:function(){var t=this;if(this.isSupported_()){this.registerRootHandlers_();var n=e.cssClasses,i=n.ROOT,a=n.UNBOUNDED;requestAnimationFrame(function(){t.adapter_.addClass(i),t.adapter_.isUnbounded()&&t.adapter_.addClass(a),t.layoutInternal_()})}}},{key:"destroy",value:function(){var t=this;if(this.isSupported_()){this.deregisterRootHandlers_(),this.deregisterDeactivationHandlers_();var n=e.cssClasses,i=n.ROOT,a=n.UNBOUNDED;requestAnimationFrame(function(){t.adapter_.removeClass(i),t.adapter_.removeClass(a),t.removeCssVars_()})}}},{key:"registerRootHandlers_",value:function(){var t=this;l.forEach(function(e){t.adapter_.registerInteractionHandler(e,t.activateHandler_)}),this.adapter_.registerInteractionHandler("focus",this.focusHandler_),this.adapter_.registerInteractionHandler("blur",this.blurHandler_),this.adapter_.registerResizeHandler(this.resizeHandler_)}},{key:"registerDeactivationHandlers_",value:function(t){var e=this;"keydown"===t.type?this.adapter_.registerInteractionHandler("keyup",this.deactivateHandler_):f.forEach(function(t){e.adapter_.registerDocumentInteractionHandler(t,e.deactivateHandler_)})}},{key:"deregisterRootHandlers_",value:function(){var t=this;l.forEach(function(e){t.adapter_.deregisterInteractionHandler(e,t.activateHandler_)}),this.adapter_.deregisterInteractionHandler("focus",this.focusHandler_),this.adapter_.deregisterInteractionHandler("blur",this.blurHandler_),this.adapter_.deregisterResizeHandler(this.resizeHandler_)}},{key:"deregisterDeactivationHandlers_",value:function(){var t=this;this.adapter_.deregisterInteractionHandler("keyup",this.deactivateHandler_),f.forEach(function(e){t.adapter_.deregisterDocumentInteractionHandler(e,t.deactivateHandler_)})}},{key:"removeCssVars_",value:function(){var t=this,n=e.strings;Object.keys(n).forEach(function(e){0===e.indexOf("VAR_")&&t.adapter_.updateCssVariable(n[e],null)})}},{key:"activate_",value:function(t){var e=this;if(!this.adapter_.isSurfaceDisabled()){var n=this.activationState_;if(!n.isActivated){var i=this.previousActivationEvent_;i&&t&&i.type!==t.type||(n.isActivated=!0,n.isProgrammatic=null===t,n.activationEvent=t,n.wasActivatedByPointer=!n.isProgrammatic&&("mousedown"===t.type||"touchstart"===t.type||"pointerdown"===t.type),t&&this.registerDeactivationHandlers_(t),requestAnimationFrame(function(){n.wasElementMadeActive=!t||"keydown"!==t.type||e.adapter_.isSurfaceActive(),n.wasElementMadeActive?e.animateActivation_():e.activationState_=e.defaultActivationState_()}))}}}},{key:"activate",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;this.activate_(t)}},{key:"animateActivation_",value:function(){var t=this,n=e.strings,i=n.VAR_FG_TRANSLATE_START,a=n.VAR_FG_TRANSLATE_END,r=e.cssClasses,o=r.FG_DEACTIVATION,s=r.FG_ACTIVATION,u=e.numbers.DEACTIVATION_TIMEOUT_MS,c="",d="";if(!this.adapter_.isUnbounded()){var l=this.getFgTranslationCoordinates_(),f=l.startPoint,v=l.endPoint;c=f.x+"px, "+f.y+"px",d=v.x+"px, "+v.y+"px"}this.adapter_.updateCssVariable(i,c),this.adapter_.updateCssVariable(a,d),clearTimeout(this.activationTimer_),clearTimeout(this.fgDeactivationRemovalTimer_),this.rmBoundedActivationClasses_(),this.adapter_.removeClass(o),this.adapter_.computeBoundingRect(),this.adapter_.addClass(s),this.activationTimer_=setTimeout(function(){return t.activationTimerCallback_()},u)}},{key:"getFgTranslationCoordinates_",value:function(){var t=this.activationState_,e=t.activationEvent,n=t.wasActivatedByPointer,i=void 0;return i=n?Object(u.getNormalizedEventCoords)(e,this.adapter_.getWindowPageOffset(),this.adapter_.computeBoundingRect()):{x:this.frame_.width/2,y:this.frame_.height/2},i={x:i.x-this.initialSize_/2,y:i.y-this.initialSize_/2},{startPoint:i,endPoint:{x:this.frame_.width/2-this.initialSize_/2,y:this.frame_.height/2-this.initialSize_/2}}}},{key:"runDeactivationUXLogicIfReady_",value:function(){var t=this,n=e.cssClasses.FG_DEACTIVATION,i=this.activationState_,a=i.hasDeactivationUXRun,r=i.isActivated;(a||!r)&&this.activationAnimationHasEnded_&&(this.rmBoundedActivationClasses_(),this.adapter_.addClass(n),this.fgDeactivationRemovalTimer_=setTimeout(function(){t.adapter_.removeClass(n)},s.b.FG_DEACTIVATION_MS))}},{key:"rmBoundedActivationClasses_",value:function(){var t=e.cssClasses.FG_ACTIVATION;this.adapter_.removeClass(t),this.activationAnimationHasEnded_=!1,this.adapter_.computeBoundingRect()}},{key:"resetActivationState_",value:function(){var t=this;this.previousActivationEvent_=this.activationState_.activationEvent,this.activationState_=this.defaultActivationState_(),setTimeout(function(){return t.previousActivationEvent_=null},e.numbers.TAP_DELAY_MS)}},{key:"deactivate_",value:function(t){var e=this,n=this.activationState_;if(n.isActivated){var i=c({},n);if(n.isProgrammatic){requestAnimationFrame(function(){return e.animateDeactivation_(null,i)}),this.resetActivationState_()}else this.deregisterDeactivationHandlers_(),requestAnimationFrame(function(){e.activationState_.hasDeactivationUXRun=!0,e.animateDeactivation_(t,i),e.resetActivationState_()})}}},{key:"deactivate",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;this.deactivate_(t)}},{key:"animateDeactivation_",value:function(t,e){var n=e.wasActivatedByPointer,i=e.wasElementMadeActive;(n||i)&&this.runDeactivationUXLogicIfReady_()}},{key:"layout",value:function(){var t=this;this.layoutFrame_&&cancelAnimationFrame(this.layoutFrame_),this.layoutFrame_=requestAnimationFrame(function(){t.layoutInternal_(),t.layoutFrame_=0})}},{key:"layoutInternal_",value:function(){this.frame_=this.adapter_.computeBoundingRect();var t=Math.max(this.frame_.height,this.frame_.width),n=Math.sqrt(Math.pow(this.frame_.width,2)+Math.pow(this.frame_.height,2));this.initialSize_=t*e.numbers.INITIAL_ORIGIN_SCALE,this.maxRadius_=n+e.numbers.PADDING,this.fgScale_=this.maxRadius_/this.initialSize_,this.xfDuration_=1e3*Math.sqrt(this.maxRadius_/1024),this.updateLayoutCssVars_()}},{key:"updateLayoutCssVars_",value:function(){var t=e.strings,n=t.VAR_FG_SIZE,i=t.VAR_LEFT,a=t.VAR_TOP,r=t.VAR_FG_SCALE;this.adapter_.updateCssVariable(n,this.initialSize_+"px"),this.adapter_.updateCssVariable(r,this.fgScale_),this.adapter_.isUnbounded()&&(this.unboundedCoords_={left:Math.round(this.frame_.width/2-this.initialSize_/2),top:Math.round(this.frame_.height/2-this.initialSize_/2)},this.adapter_.updateCssVariable(i,this.unboundedCoords_.left+"px"),this.adapter_.updateCssVariable(a,this.unboundedCoords_.top+"px"))}},{key:"setUnbounded",value:function(t){var n=e.cssClasses.UNBOUNDED;t?this.adapter_.addClass(n):this.adapter_.removeClass(n)}}]),e}(o.a);e.a=v},7:function(t,e,n){"use strict";n.d(e,"a",function(){return i}),n.d(e,"c",function(){return a}),n.d(e,"b",function(){return r});/** | ||
var u=void 0,c=void 0},3:function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var a=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}();!function(){function t(){i(this,t)}a(t,[{key:"browserSupportsCssVars",value:function(){}},{key:"isUnbounded",value:function(){}},{key:"isSurfaceActive",value:function(){}},{key:"isSurfaceDisabled",value:function(){}},{key:"addClass",value:function(t){}},{key:"removeClass",value:function(t){}},{key:"containsEventTarget",value:function(t){}},{key:"registerInteractionHandler",value:function(t,e){}},{key:"deregisterInteractionHandler",value:function(t,e){}},{key:"registerDocumentInteractionHandler",value:function(t,e){}},{key:"deregisterDocumentInteractionHandler",value:function(t,e){}},{key:"registerResizeHandler",value:function(t){}},{key:"deregisterResizeHandler",value:function(t){}},{key:"updateCssVariable",value:function(t,e){}},{key:"computeBoundingRect",value:function(){}},{key:"getWindowPageOffset",value:function(){}}])}()},4:function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function r(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}Object.defineProperty(e,"__esModule",{value:!0}),n.d(e,"MDCRipple",function(){return d}),n.d(e,"RippleCapableSurface",function(){return l});var o=n(1),s=(n(3),n(6)),u=n(2);n.d(e,"MDCRippleFoundation",function(){return s.a}),n.d(e,"util",function(){return u});var c=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}(),d=function(t){function e(){var t;i(this,e);for(var n=arguments.length,r=Array(n),o=0;o<n;o++)r[o]=arguments[o];var s=a(this,(t=e.__proto__||Object.getPrototypeOf(e)).call.apply(t,[this].concat(r)));return s.disabled=!1,s.unbounded_,s}return r(e,t),c(e,[{key:"setUnbounded_",value:function(){this.foundation_.setUnbounded(this.unbounded_)}},{key:"activate",value:function(){this.foundation_.activate()}},{key:"deactivate",value:function(){this.foundation_.deactivate()}},{key:"layout",value:function(){this.foundation_.layout()}},{key:"getDefaultFoundation",value:function(){return new s.a(e.createAdapter(this))}},{key:"initialSyncWithDOM",value:function(){this.unbounded="mdcRippleIsUnbounded"in this.root_.dataset}},{key:"unbounded",get:function(){return this.unbounded_},set:function(t){this.unbounded_=Boolean(t),this.setUnbounded_()}}],[{key:"attachTo",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=n.isUnbounded,a=void 0===i?void 0:i,r=new e(t);return void 0!==a&&(r.unbounded=a),r}},{key:"createAdapter",value:function(t){var e=u.getMatchesProperty(HTMLElement.prototype);return{browserSupportsCssVars:function(){return u.supportsCssVariables(window)},isUnbounded:function(){return t.unbounded},isSurfaceActive:function(){return t.root_[e](":active")},isSurfaceDisabled:function(){return t.disabled},addClass:function(e){return t.root_.classList.add(e)},removeClass:function(e){return t.root_.classList.remove(e)},containsEventTarget:function(e){return t.root_.contains(e)},registerInteractionHandler:function(e,n){return t.root_.addEventListener(e,n,u.applyPassive())},deregisterInteractionHandler:function(e,n){return t.root_.removeEventListener(e,n,u.applyPassive())},registerDocumentInteractionHandler:function(t,e){return document.documentElement.addEventListener(t,e,u.applyPassive())},deregisterDocumentInteractionHandler:function(t,e){return document.documentElement.removeEventListener(t,e,u.applyPassive())},registerResizeHandler:function(t){return window.addEventListener("resize",t)},deregisterResizeHandler:function(t){return window.removeEventListener("resize",t)},updateCssVariable:function(e,n){return t.root_.style.setProperty(e,n)},computeBoundingRect:function(){return t.root_.getBoundingClientRect()},getWindowPageOffset:function(){return{x:window.pageXOffset,y:window.pageYOffset}}}}}]),e}(o.a),l=function t(){i(this,t)};l.prototype.root_,l.prototype.unbounded,l.prototype.disabled},6:function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function r(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var o=n(0),s=(n(3),n(7)),u=n(2),c=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var i in n)Object.prototype.hasOwnProperty.call(n,i)&&(t[i]=n[i])}return t},d=function(){function t(t,e){for(var n=0;n<e.length;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}return function(e,n,i){return n&&t(e.prototype,n),i&&t(e,i),e}}(),l=["touchstart","pointerdown","mousedown","keydown"],f=["touchend","pointerup","mouseup"],v=[],p=function(t){function e(t){i(this,e);var n=a(this,(e.__proto__||Object.getPrototypeOf(e)).call(this,c(e.defaultAdapter,t)));return n.layoutFrame_=0,n.frame_={width:0,height:0},n.activationState_=n.defaultActivationState_(),n.initialSize_=0,n.maxRadius_=0,n.activateHandler_=function(t){return n.activate_(t)},n.deactivateHandler_=function(t){return n.deactivate_(t)},n.focusHandler_=function(){return requestAnimationFrame(function(){return n.adapter_.addClass(e.cssClasses.BG_FOCUSED)})},n.blurHandler_=function(){return requestAnimationFrame(function(){return n.adapter_.removeClass(e.cssClasses.BG_FOCUSED)})},n.resizeHandler_=function(){return n.layout()},n.unboundedCoords_={left:0,top:0},n.fgScale_=0,n.activationTimer_=0,n.fgDeactivationRemovalTimer_=0,n.activationAnimationHasEnded_=!1,n.activationTimerCallback_=function(){n.activationAnimationHasEnded_=!0,n.runDeactivationUXLogicIfReady_()},n.previousActivationEvent_=null,n}return r(e,t),d(e,null,[{key:"cssClasses",get:function(){return s.a}},{key:"strings",get:function(){return s.c}},{key:"numbers",get:function(){return s.b}},{key:"defaultAdapter",get:function(){return{browserSupportsCssVars:function(){},isUnbounded:function(){},isSurfaceActive:function(){},isSurfaceDisabled:function(){},addClass:function(){},removeClass:function(){},containsEventTarget:function(){},registerInteractionHandler:function(){},deregisterInteractionHandler:function(){},registerDocumentInteractionHandler:function(){},deregisterDocumentInteractionHandler:function(){},registerResizeHandler:function(){},deregisterResizeHandler:function(){},updateCssVariable:function(){},computeBoundingRect:function(){},getWindowPageOffset:function(){}}}}]),d(e,[{key:"isSupported_",value:function(){return this.adapter_.browserSupportsCssVars()}},{key:"defaultActivationState_",value:function(){return{isActivated:!1,hasDeactivationUXRun:!1,wasActivatedByPointer:!1,wasElementMadeActive:!1,activationEvent:null,isProgrammatic:!1}}},{key:"init",value:function(){var t=this;if(this.isSupported_()){this.registerRootHandlers_();var n=e.cssClasses,i=n.ROOT,a=n.UNBOUNDED;requestAnimationFrame(function(){t.adapter_.addClass(i),t.adapter_.isUnbounded()&&t.adapter_.addClass(a),t.layoutInternal_()})}}},{key:"destroy",value:function(){var t=this;if(this.isSupported_()){this.deregisterRootHandlers_(),this.deregisterDeactivationHandlers_();var n=e.cssClasses,i=n.ROOT,a=n.UNBOUNDED;requestAnimationFrame(function(){t.adapter_.removeClass(i),t.adapter_.removeClass(a),t.removeCssVars_()})}}},{key:"registerRootHandlers_",value:function(){var t=this;l.forEach(function(e){t.adapter_.registerInteractionHandler(e,t.activateHandler_)}),this.adapter_.registerInteractionHandler("focus",this.focusHandler_),this.adapter_.registerInteractionHandler("blur",this.blurHandler_),this.adapter_.registerResizeHandler(this.resizeHandler_)}},{key:"registerDeactivationHandlers_",value:function(t){var e=this;"keydown"===t.type?this.adapter_.registerInteractionHandler("keyup",this.deactivateHandler_):f.forEach(function(t){e.adapter_.registerDocumentInteractionHandler(t,e.deactivateHandler_)})}},{key:"deregisterRootHandlers_",value:function(){var t=this;l.forEach(function(e){t.adapter_.deregisterInteractionHandler(e,t.activateHandler_)}),this.adapter_.deregisterInteractionHandler("focus",this.focusHandler_),this.adapter_.deregisterInteractionHandler("blur",this.blurHandler_),this.adapter_.deregisterResizeHandler(this.resizeHandler_)}},{key:"deregisterDeactivationHandlers_",value:function(){var t=this;this.adapter_.deregisterInteractionHandler("keyup",this.deactivateHandler_),f.forEach(function(e){t.adapter_.deregisterDocumentInteractionHandler(e,t.deactivateHandler_)})}},{key:"removeCssVars_",value:function(){var t=this,n=e.strings;Object.keys(n).forEach(function(e){0===e.indexOf("VAR_")&&t.adapter_.updateCssVariable(n[e],null)})}},{key:"activate_",value:function(t){var e=this;if(!this.adapter_.isSurfaceDisabled()){var n=this.activationState_;if(!n.isActivated){var i=this.previousActivationEvent_;if(!(i&&t&&i.type!==t.type)){n.isActivated=!0,n.isProgrammatic=null===t,n.activationEvent=t,n.wasActivatedByPointer=!n.isProgrammatic&&("mousedown"===t.type||"touchstart"===t.type||"pointerdown"===t.type);if(t&&v.length>0&&v.some(function(t){return e.adapter_.containsEventTarget(t)}))return void this.resetActivationState_();t&&(v.push(t.target),this.registerDeactivationHandlers_(t)),requestAnimationFrame(function(){n.wasElementMadeActive=!t||"keydown"!==t.type||e.adapter_.isSurfaceActive(),n.wasElementMadeActive?e.animateActivation_():e.activationState_=e.defaultActivationState_(),v=[]})}}}}},{key:"activate",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;this.activate_(t)}},{key:"animateActivation_",value:function(){var t=this,n=e.strings,i=n.VAR_FG_TRANSLATE_START,a=n.VAR_FG_TRANSLATE_END,r=e.cssClasses,o=r.FG_DEACTIVATION,s=r.FG_ACTIVATION,u=e.numbers.DEACTIVATION_TIMEOUT_MS,c="",d="";if(!this.adapter_.isUnbounded()){var l=this.getFgTranslationCoordinates_(),f=l.startPoint,v=l.endPoint;c=f.x+"px, "+f.y+"px",d=v.x+"px, "+v.y+"px"}this.adapter_.updateCssVariable(i,c),this.adapter_.updateCssVariable(a,d),clearTimeout(this.activationTimer_),clearTimeout(this.fgDeactivationRemovalTimer_),this.rmBoundedActivationClasses_(),this.adapter_.removeClass(o),this.adapter_.computeBoundingRect(),this.adapter_.addClass(s),this.activationTimer_=setTimeout(function(){return t.activationTimerCallback_()},u)}},{key:"getFgTranslationCoordinates_",value:function(){var t=this.activationState_,e=t.activationEvent,n=t.wasActivatedByPointer,i=void 0;return i=n?Object(u.getNormalizedEventCoords)(e,this.adapter_.getWindowPageOffset(),this.adapter_.computeBoundingRect()):{x:this.frame_.width/2,y:this.frame_.height/2},i={x:i.x-this.initialSize_/2,y:i.y-this.initialSize_/2},{startPoint:i,endPoint:{x:this.frame_.width/2-this.initialSize_/2,y:this.frame_.height/2-this.initialSize_/2}}}},{key:"runDeactivationUXLogicIfReady_",value:function(){var t=this,n=e.cssClasses.FG_DEACTIVATION,i=this.activationState_,a=i.hasDeactivationUXRun,r=i.isActivated;(a||!r)&&this.activationAnimationHasEnded_&&(this.rmBoundedActivationClasses_(),this.adapter_.addClass(n),this.fgDeactivationRemovalTimer_=setTimeout(function(){t.adapter_.removeClass(n)},s.b.FG_DEACTIVATION_MS))}},{key:"rmBoundedActivationClasses_",value:function(){var t=e.cssClasses.FG_ACTIVATION;this.adapter_.removeClass(t),this.activationAnimationHasEnded_=!1,this.adapter_.computeBoundingRect()}},{key:"resetActivationState_",value:function(){var t=this;this.previousActivationEvent_=this.activationState_.activationEvent,this.activationState_=this.defaultActivationState_(),setTimeout(function(){return t.previousActivationEvent_=null},e.numbers.TAP_DELAY_MS)}},{key:"deactivate_",value:function(t){var e=this,n=this.activationState_;if(n.isActivated){var i=c({},n);if(n.isProgrammatic){requestAnimationFrame(function(){return e.animateDeactivation_(null,i)}),this.resetActivationState_()}else this.deregisterDeactivationHandlers_(),requestAnimationFrame(function(){e.activationState_.hasDeactivationUXRun=!0,e.animateDeactivation_(t,i),e.resetActivationState_()})}}},{key:"deactivate",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null;this.deactivate_(t)}},{key:"animateDeactivation_",value:function(t,e){var n=e.wasActivatedByPointer,i=e.wasElementMadeActive;(n||i)&&this.runDeactivationUXLogicIfReady_()}},{key:"layout",value:function(){var t=this;this.layoutFrame_&&cancelAnimationFrame(this.layoutFrame_),this.layoutFrame_=requestAnimationFrame(function(){t.layoutInternal_(),t.layoutFrame_=0})}},{key:"layoutInternal_",value:function(){var t=this;this.frame_=this.adapter_.computeBoundingRect();var n=Math.max(this.frame_.height,this.frame_.width);this.maxRadius_=this.adapter_.isUnbounded()?n:function(){return Math.sqrt(Math.pow(t.frame_.width,2)+Math.pow(t.frame_.height,2))+e.numbers.PADDING}(),this.initialSize_=n*e.numbers.INITIAL_ORIGIN_SCALE,this.fgScale_=this.maxRadius_/this.initialSize_,this.updateLayoutCssVars_()}},{key:"updateLayoutCssVars_",value:function(){var t=e.strings,n=t.VAR_FG_SIZE,i=t.VAR_LEFT,a=t.VAR_TOP,r=t.VAR_FG_SCALE;this.adapter_.updateCssVariable(n,this.initialSize_+"px"),this.adapter_.updateCssVariable(r,this.fgScale_),this.adapter_.isUnbounded()&&(this.unboundedCoords_={left:Math.round(this.frame_.width/2-this.initialSize_/2),top:Math.round(this.frame_.height/2-this.initialSize_/2)},this.adapter_.updateCssVariable(i,this.unboundedCoords_.left+"px"),this.adapter_.updateCssVariable(a,this.unboundedCoords_.top+"px"))}},{key:"setUnbounded",value:function(t){var n=e.cssClasses.UNBOUNDED;t?this.adapter_.addClass(n):this.adapter_.removeClass(n)}}]),e}(o.a);e.a=p},7:function(t,e,n){"use strict";n.d(e,"a",function(){return i}),n.d(e,"c",function(){return a}),n.d(e,"b",function(){return r});/** | ||
* @license | ||
@@ -40,2 +40,3 @@ * Copyright 2016 Google Inc. All Rights Reserved. | ||
*/ | ||
var i={ROOT:"mdc-ripple-upgraded",UNBOUNDED:"mdc-ripple-upgraded--unbounded",BG_FOCUSED:"mdc-ripple-upgraded--background-focused",FG_ACTIVATION:"mdc-ripple-upgraded--foreground-activation",FG_DEACTIVATION:"mdc-ripple-upgraded--foreground-deactivation"},a={VAR_LEFT:"--mdc-ripple-left",VAR_TOP:"--mdc-ripple-top",VAR_FG_SIZE:"--mdc-ripple-fg-size",VAR_FG_SCALE:"--mdc-ripple-fg-scale",VAR_FG_TRANSLATE_START:"--mdc-ripple-fg-translate-start",VAR_FG_TRANSLATE_END:"--mdc-ripple-fg-translate-end"},r={PADDING:10,INITIAL_ORIGIN_SCALE:.6,DEACTIVATION_TIMEOUT_MS:225,FG_DEACTIVATION_MS:150,TAP_DELAY_MS:300}},87:function(t,e,n){t.exports=n(5)}})}); | ||
var i={ROOT:"mdc-ripple-upgraded",UNBOUNDED:"mdc-ripple-upgraded--unbounded",BG_FOCUSED:"mdc-ripple-upgraded--background-focused",FG_ACTIVATION:"mdc-ripple-upgraded--foreground-activation",FG_DEACTIVATION:"mdc-ripple-upgraded--foreground-deactivation"},a={VAR_LEFT:"--mdc-ripple-left",VAR_TOP:"--mdc-ripple-top",VAR_FG_SIZE:"--mdc-ripple-fg-size",VAR_FG_SCALE:"--mdc-ripple-fg-scale",VAR_FG_TRANSLATE_START:"--mdc-ripple-fg-translate-start",VAR_FG_TRANSLATE_END:"--mdc-ripple-fg-translate-end"},r={PADDING:10,INITIAL_ORIGIN_SCALE:.6,DEACTIVATION_TIMEOUT_MS:225,FG_DEACTIVATION_MS:150,TAP_DELAY_MS:300}},99:function(t,e,n){t.exports=n(4)}})}); | ||
//# sourceMappingURL=mdc.ripple.min.js.map |
@@ -69,2 +69,6 @@ /** | ||
// Tracks activations that have occurred on the current frame, to avoid simultaneous nested activations | ||
/** @type {!Array<!EventTarget>} */ | ||
let activatedTargets = []; | ||
/** | ||
@@ -94,2 +98,3 @@ * @extends {MDCFoundation<!MDCRippleAdapter>} | ||
removeClass: (/* className: string */) => {}, | ||
containsEventTarget: (/* target: !EventTarget */) => {}, | ||
registerInteractionHandler: (/* evtType: string, handler: EventListener */) => {}, | ||
@@ -120,5 +125,2 @@ deregisterInteractionHandler: (/* evtType: string, handler: EventListener */) => {}, | ||
/** @private {number} */ | ||
this.xfDuration_ = 0; | ||
/** @private {number} */ | ||
this.initialSize_ = 0; | ||
@@ -294,3 +296,3 @@ | ||
const {activationState_: activationState} = this; | ||
const activationState = this.activationState_; | ||
if (activationState.isActivated) { | ||
@@ -314,3 +316,12 @@ return; | ||
const hasActivatedChild = | ||
e && activatedTargets.length > 0 && activatedTargets.some((target) => this.adapter_.containsEventTarget(target)); | ||
if (hasActivatedChild) { | ||
// Immediately reset activation state, while preserving logic that prevents touch follow-on events | ||
this.resetActivationState_(); | ||
return; | ||
} | ||
if (e) { | ||
activatedTargets.push(/** @type {!EventTarget} */ (e.target)); | ||
this.registerDeactivationHandlers_(e); | ||
@@ -332,2 +343,5 @@ } | ||
} | ||
// Reset array on next frame after the current event has had a chance to bubble to prevent ancestor ripples | ||
activatedTargets = []; | ||
}); | ||
@@ -377,4 +391,3 @@ } | ||
getFgTranslationCoordinates_() { | ||
const {activationState_: activationState} = this; | ||
const {activationEvent, wasActivatedByPointer} = activationState; | ||
const {activationEvent, wasActivatedByPointer} = this.activationState_; | ||
@@ -498,13 +511,21 @@ let startPoint; | ||
this.frame_ = this.adapter_.computeBoundingRect(); | ||
const maxDim = Math.max(this.frame_.height, this.frame_.width); | ||
const surfaceDiameter = Math.sqrt(Math.pow(this.frame_.width, 2) + Math.pow(this.frame_.height, 2)); | ||
// 60% of the largest dimension of the surface | ||
// Surface diameter is treated differently for unbounded vs. bounded ripples. | ||
// Unbounded ripple diameter is calculated smaller since the surface is expected to already be padded appropriately | ||
// to extend the hitbox, and the ripple is expected to meet the edges of the padded hitbox (which is typically | ||
// square). Bounded ripples, on the other hand, are fully expected to expand beyond the surface's longest diameter | ||
// (calculated based on the diagonal plus a constant padding), and are clipped at the surface's border via | ||
// `overflow: hidden`. | ||
const getBoundedRadius = () => { | ||
const hypotenuse = Math.sqrt(Math.pow(this.frame_.width, 2) + Math.pow(this.frame_.height, 2)); | ||
return hypotenuse + MDCRippleFoundation.numbers.PADDING; | ||
}; | ||
this.maxRadius_ = this.adapter_.isUnbounded() ? maxDim : getBoundedRadius(); | ||
// Ripple is sized as a fraction of the largest dimension of the surface, then scales up using a CSS scale transform | ||
this.initialSize_ = maxDim * MDCRippleFoundation.numbers.INITIAL_ORIGIN_SCALE; | ||
this.fgScale_ = this.maxRadius_ / this.initialSize_; | ||
// Diameter of the surface + 10px | ||
this.maxRadius_ = surfaceDiameter + MDCRippleFoundation.numbers.PADDING; | ||
this.fgScale_ = this.maxRadius_ / this.initialSize_; | ||
this.xfDuration_ = 1000 * Math.sqrt(this.maxRadius_ / 1024); | ||
this.updateLayoutCssVars_(); | ||
@@ -511,0 +532,0 @@ } |
@@ -66,2 +66,3 @@ /** | ||
removeClass: (className) => instance.root_.classList.remove(className), | ||
containsEventTarget: (target) => instance.root_.contains(target), | ||
registerInteractionHandler: (evtType, handler) => | ||
@@ -68,0 +69,0 @@ instance.root_.addEventListener(evtType, handler, util.applyPassive()), |
{ | ||
"name": "@material/ripple", | ||
"description": "The Material Components for the web Ink Ripple effect for web element interactions", | ||
"version": "0.29.0", | ||
"version": "0.30.0", | ||
"license": "Apache-2.0", | ||
@@ -18,4 +18,4 @@ "keywords": [ | ||
"@material/base": "^0.29.0", | ||
"@material/theme": "^0.29.0" | ||
"@material/theme": "^0.30.0" | ||
} | ||
} |
452
README.md
@@ -10,3 +10,3 @@ <!--docs: | ||
# Ripples | ||
# Ripple | ||
@@ -17,33 +17,13 @@ MDC Ripple provides the JavaScript and CSS required to provide components (or any element at all) with a material "ink ripple" interaction effect. It is designed to be efficient, uninvasive, and usable without adding any extra DOM to your elements. | ||
## Table of Contents | ||
## Design & API Documentation | ||
- [An aside regarding browser support](#an-aside-regarding-browser-support) | ||
- [Installation](#installation) | ||
- [Usage](#usage) | ||
- [Adding Ripple styles](#adding-ripple-styles) | ||
- [Adding Ripple JS](#adding-ripple-js) | ||
- [Ripple JS API](#ripple-js-api) | ||
- [Unbounded Ripples](#unbounded-ripples) | ||
- [The mdc-ripple-surface class](#the-mdc-ripple-surface-class) | ||
- [Using the foundation](#using-the-foundation) | ||
- [Using the vanilla DOM adapter](#using-the-vanilla-dom-adapter) | ||
- [Tips/Tricks](#tipstricks) | ||
- [Integrating ripples into MDC Web components](#integrating-ripples-into-mdc-web-components) | ||
- [Using a sentinel element for a ripple](#using-a-sentinel-element-for-a-ripple) | ||
- [Keyboard interaction for custom UI components](#keyboard-interaction-for-custom-ui-components) | ||
- [Specifying known element dimensions](#specifying-known-element-dimensions) | ||
- [Caveat: Edge](#caveat-edge) | ||
- [Caveat: Safari 9](#caveat-safari) | ||
- [Caveat: Mobile Safari](#caveat-mobile-safari) | ||
- [Caveat: Theme Custom Variables](#caveat-theme-custom-variables) | ||
- [The util API](#the-util-api) | ||
<ul class="icon-list"> | ||
<li class="icon-list-item icon-list-item--spec"> | ||
<a href="https://material.io/guidelines/motion/choreography.html#choreography-radial-reaction">Material Design guidelines: Choreography</a> | ||
</li> | ||
<li class="icon-list-item icon-list-item--link"> | ||
<a href="https://material-components-web.appspot.com/ripple.html">Demo</a> | ||
</li> | ||
</ul> | ||
### An aside regarding browser support | ||
In order to function correctly, MDC Ripple requires a _browser_ implementation of [CSS Variables](https://www.w3.org/TR/css-variables/). MDC Ripple uses custom properties to dynamically position pseudo elements, which allows us to not need any extra DOM for this effect. | ||
Because we rely on scoped, dynamic CSS variables, static pre-processors such as [postcss-custom-properties](https://github.com/postcss/postcss-custom-properties) will not work as an adequate polyfill ([...yet?](https://github.com/postcss/postcss-custom-properties/issues/32)). | ||
Edge and Safari 9, although they do [support CSS variables](http://caniuse.com/#feat=css-variables), do not support MDC Ripple. See the respective caveats for [Edge](#caveat-edge) and [Safari 9](#caveat-safari) for an explanation. | ||
## Installation | ||
@@ -57,90 +37,92 @@ | ||
### Adding Ripple styles | ||
A ripple can be applied to a variety of elements to represent interactive surfaces. Several MDC Web components, such as Button, FAB, Checkbox and Radio, also use ripples. | ||
General notes: | ||
A ripple can be added to an element through either a JavaScript or CSS-only implementation. When a ripple is initialized on an element using JS, it dynamically adds a `mdc-ripple-upgraded` class to that element. If ripple JS is not initialized but Sass mixins are included on the element, the ripple uses a simpler CSS-only implementation which relies on the `:hover`, `:focus`, and `:active` pseudo-classes. | ||
* Ripple mixins can be applied to a variety of elements representing interactive surfaces. These mixins are also used by other MDC Web components such as Button, FAB, Checkbox, Radio, etc. | ||
* Surfaces for bounded ripples should have `overflow` set to `hidden`, while surfaces for unbounded ripples should have it set to `visible` | ||
* When a ripple is successfully initialized on an element using JS, it dynamically adds a `mdc-ripple-upgraded` class to that element. If ripple JS is not initialized but Sass mixins are included on the surface, the ripple will still work, but it uses a simpler, CSS-only implementation which relies on `:hover`, `:focus`, and `:active`. | ||
### CSS Classes | ||
#### Sass API | ||
CSS Class | Description | ||
--- | --- | ||
`mdc-ripple-surface` | Adds a ripple to the element | ||
`mdc-ripple-surface--primary` | Sets the ripple color to the theme primary color | ||
`mdc-ripple-surface--accent` | Sets the ripple color to the theme secondary color | ||
In order to fully style states as well as the ripple effect for pressed state, both `mdc-ripple` mixins below must be included, as well as either the basic or advanced `mdc-states` mixins documented below. | ||
### Sass Mixins | ||
Once these styles are in place for a component, it is feasible to further override only the parts necessary (e.g. `mdc-states` specifically) for specific variants (e.g. for flat vs. raised buttons). | ||
In order to fully style the ripple effect for different states (hover/focus/pressed), the following mixins must be included: | ||
These APIs implicitly use pseudo-elements for the ripple effect: `::before` for the background, and `::after` for the foreground. | ||
* `mdc-ripple-surface`, for base styles | ||
* Either `mdc-ripple-radius-bounded` or `mdc-ripple-radius-unbounded`, to appropriately size the ripple on the surface | ||
* Either the basic or advanced `mdc-states` mixins, as explained below | ||
##### Ripple Mixins | ||
##### Using basic states mixins | ||
```css | ||
.my-surface { | ||
@include mdc-ripple-surface; | ||
@include mdc-ripple-radius-bounded; | ||
@include mdc-states; | ||
} | ||
``` | ||
Mixin | Description | ||
--- | --- | ||
`mdc-ripple-surface` | Adds base styles for a ripple surface | ||
`mdc-ripple-radius($radius)` | Adds styles for the radius of the ripple effect,<br>for both bounded and unbounded ripples | ||
##### Using advanced states mixins | ||
```css | ||
.my-surface { | ||
@include mdc-ripple-surface; | ||
@include mdc-ripple-radius-bounded; | ||
@include mdc-states-base-color(black); | ||
@include mdc-states-hover-opacity(.1); | ||
@include mdc-states-focus-opacity(.3); | ||
@include mdc-states-press-opacity(.4); | ||
} | ||
``` | ||
##### Basic States Mixins | ||
These APIs use pseudo-elements for the ripple effect: `::before` for the background, and `::after` for the foreground. | ||
When using the basic states mixins, inclusion of the `mdc-states` mixin is mandatory. | ||
Inclusion of `mdc-states-activated` or `mdc-states-selected` is optional, depending on whether activated or selected | ||
states are applicable to the component in question. | ||
#### Ripple Mixins | ||
Mixin | Description | ||
--- | --- | ||
`mdc-states($color, $has-nested-focusable-element)` | Adds state and ripple styles using the indicated color, deciding opacities based on whether the passed color is light or dark.<br>`$has-nested-focusable-element` defaults to `false` but should be set to `true` if the component contains a focusable element (e.g. an input) under the root node. | ||
`mdc-states-activated($color, $has-nested-focusable-element)` | Adds state and ripple styles for activated states using the indicated color, deciding opacities based on whether the passed color is light or dark.<br>`$has-nested-focusable-element` defaults to `false` but should be set to `true` if the component contains a focusable element (e.g. an input) under the root node. | ||
`mdc-states-selected($color, $has-nested-focusable-element)` | Adds state and ripple styles for selected states using the indicated color, deciding opacities based on whether the passed color is light or dark.<br>`$has-nested-focusable-element` defaults to `false` but should be set to `true` if the component contains a focusable element (e.g. an input) under the root node. | ||
`mdc-ripple-surface` | Mandatory. Adds base styles for a ripple surface | ||
`mdc-ripple-radius-bounded($radius)` | Adds styles for the radius of the ripple effect,<br>for bounded ripple surfaces | ||
`mdc-ripple-radius-unbounded($radius)` | Adds styles for the radius of the ripple effect,<br>for unbounded ripple surfaces | ||
##### Advanced States Mixins | ||
> _NOTE_: It is mandatory to include _either_ `mdc-ripple-radius-bounded` or `mdc-ripple-radius-unbounded`. In both cases, `$radius` is optional and defaults to `100%`. | ||
When using the advanced states mixins, every one of the mixins below should be included at least once to establish base | ||
styles for states. | ||
#### Basic States Mixins | ||
These mixins can also be used to emit activated or selected styles if applicable, by applying them within a selector for | ||
`&--activated` or `&--selected` modifier classes. | ||
Mixin | Description | ||
--- | --- | ||
`mdc-states-base-color($color)` | Sets up base state styles using the provided color | ||
`mdc-states-hover-opacity($opacity)` | Adds styles for hover state using the provided opacity | ||
`mdc-states-focus-opacity($opacity, $has-nested-focusable-element)` | Adds styles for focus state using the provided opacity. `$has-nested-focusable-element` defaults to `false` but should be set to `true` if the component contains a focusable element (e.g. an input) under the root node. | ||
`mdc-states-press-opacity($opacity)` | Adds styles for press state using the provided opacity | ||
`mdc-states($color, $has-nested-focusable-element)` | Mandatory. Adds state and ripple styles in the given color | ||
`mdc-states-activated($color, $has-nested-focusable-element)` | Optional. Adds state and ripple styles for activated states in the given color | ||
`mdc-states-selected($color, $has-nested-focusable-element)` | Optional. Adds state and ripple styles for selected states in the given color | ||
### Adding Ripple JS | ||
> _NOTE_: Each of the mixins above adds ripple styles using the indicated color, deciding opacity values based on whether the passed color is light or dark. | ||
First import the ripple JS. | ||
> _NOTE_: `$has-nested-focusable-element` defaults to `false` but should be set to `true` if the component contains a focusable element (e.g. an input) inside the root element. | ||
#### ES2015 | ||
#### Advanced States Mixins | ||
```javascript | ||
import {MDCRipple, MDCRippleFoundation, util} from '@material/ripple'; | ||
``` | ||
When using the advanced states mixins instead of the basic states mixins, every one of the mixins below should be included at least once. | ||
##### CommonJS | ||
These mixins can also be used to emit activated or selected styles, by applying them within a selector for | ||
`&--activated` or `&--selected` modifier classes. | ||
```javascript | ||
const {MDCRipple, MDCRippleFoundation, util} = require('@material/ripple'); | ||
``` | ||
Mixin | Description | ||
--- | --- | ||
`mdc-states-base-color($color)` | Mandatory. Sets up base state styles using the provided color | ||
`mdc-states-hover-opacity($opacity)` | Mandatory. Adds styles for hover state using the provided opacity | ||
`mdc-states-focus-opacity($opacity, $has-nested-focusable-element)` | Mandatory. Adds styles for focus state using the provided opacity | ||
`mdc-states-press-opacity($opacity)` | Mandatory. Adds styles for press state using the provided opacity | ||
#### AMD | ||
> _NOTE_: `$has-nested-focusable-element` defaults to `false` but should be set to `true` if the component contains a focusable element (e.g. an input) inside the root element. | ||
```javascript | ||
require('path/to/@material/ripple', function(mdcRipple) { | ||
const MDCRipple = mdcRipple.MDCRipple; | ||
const MDCRippleFoundation = mdcRipple.MDCRippleFoundation; | ||
const util = mdcRipple.util; | ||
}); | ||
``` | ||
### `MDCRipple` | ||
#### Global | ||
The `MDCRipple` JavaScript component allows for programmatic activation / deactivation of the ripple, for interdependent interaction between | ||
components. For example, this is used for making form field labels trigger the ripples in their corresponding input elements. | ||
```javascript | ||
const MDCRipple = mdc.ripple.MDCRipple; | ||
const MDCRippleFoundation = mdc.ripple.MDCRippleFoundation; | ||
const util = mdc.ripple.util; | ||
``` | ||
To use the `MDCRipple` component, first [import the `MDCRipple` JS](../../docs/importing-js.md). Then, initialize the ripple with the correct DOM element. | ||
Then, simply initialize the ripple with the correct DOM element. | ||
```javascript | ||
const surface = document.querySelector('.surface'); | ||
const surface = document.querySelector('.my-surface'); | ||
const ripple = new MDCRipple(surface); | ||
@@ -153,34 +135,68 @@ ``` | ||
```javascript | ||
MDCRipple.attachTo(document.querySelector('.surface')); | ||
MDCRipple.attachTo(document.querySelector('.my-surface')); | ||
``` | ||
### Ripple JS API | ||
Property | Value Type | Description | ||
--- | --- | --- | ||
`unbounded` | Boolean | Whether or not the ripple is unbounded | ||
> _NOTE_: Surfaces for bounded ripples should have the `overflow` property set to `hidden`, while surfaces for unbounded ripples should have it set to `visible`. | ||
The component allows for programmatic activation / deactivation of the ripple, for interdependent interaction between | ||
components. This is used for making form field labels trigger the ripples in their corresponding input elements, for | ||
example. | ||
Method Signature | Description | ||
--- | --- | ||
`activate() => void` | Proxies to the foundation's `activate` method | ||
`deactivate() => void` | Proxies to the foundation's `deactivate` method | ||
`layout() => void` | Proxies to the foundation's `layout` method | ||
#### MDCRipple.activate() | ||
### `MDCRippleAdapter` | ||
Triggers an activation of the ripple (the first stage, which happens when the ripple surface is engaged via interaction, | ||
such as a `mousedown` or a `pointerdown` event). It expands from the center. | ||
| Method Signature | Description | | ||
| --- | --- | | ||
| `browserSupportsCssVars() => boolean` | Whether or not the given browser supports CSS Variables. | | ||
| `isUnbounded() => boolean` | Whether or not the ripple should be considered unbounded. | | ||
| `isSurfaceActive() => boolean` | Whether or not the surface the ripple is acting upon is [active](https://www.w3.org/TR/css3-selectors/#useraction-pseudos) | | ||
| `isSurfaceDisabled() => boolean` | Whether or not the ripple is attached to a disabled component | | ||
| `addClass(className: string) => void` | Adds a class to the ripple surface | | ||
| `removeClass(className: string) => void` | Removes a class from the ripple surface | | ||
| `containsEventTarget(target: EventTarget) => boolean` | Whether or not the ripple surface contains the given event target | | ||
| `registerInteractionHandler(evtType: string, handler: EventListener) => void` | Registers an event handler on the ripple surface | | ||
| `deregisterInteractionHandler(evtType: string, handler: EventListener) => void` | Unregisters an event handler on the ripple surface | | ||
| `registerDocumentInteractionHandler(evtType: string, handler: EventListener) => void` | Registers an event handler on the documentElement | | ||
| `deregisterDocumentInteractionHandler(evtType: string, handler: EventListener) => void` | Unregisters an event handler on the documentElement | | ||
| `registerResizeHandler(handler: Function) => void` | Registers a handler to be called when the ripple surface (or its viewport) resizes | | ||
| `deregisterResizeHandler(handler: Function) => void` | Unregisters a handler to be called when the ripple surface (or its viewport) resizes | | ||
| `updateCssVariable(varName: string, value: (string or null)) => void` | Sets the CSS property `varName` on the ripple surface to the value specified | | ||
| `computeBoundingRect() => ClientRect` | Returns the ClientRect for the surface | | ||
| `getWindowPageOffset() => {x: number, y: number}` | Returns the `page{X,Y}Offset` values for the window object | | ||
#### MDCRipple.deactivate() | ||
> _NOTE_: When implementing `browserSupportsCssVars`, please take the [Edge](#caveat-edge) and [Safari 9](#caveat-safari) considerations into account. We provide a `supportsCssVariables` function within the `util.js` which we recommend using, as it handles this for you. | ||
Triggers a deactivation of the ripple (the second stage, which happens when the ripple surface is engaged via | ||
interaction, such as a `mouseup` or a `pointerup` event). It expands from the center. | ||
### `MDCRippleFoundation` | ||
#### MDCRipple.layout() | ||
Method Signature | Description | ||
--- | --- | ||
`activate() => void` | Triggers an activation of the ripple (the first stage, which happens when the ripple surface is engaged via interaction, such as a `mousedown` or a `pointerdown` event). It expands from the center. | ||
`deactivate() => void` | Triggers a deactivation of the ripple (the second stage, which happens when the ripple surface is engaged via interaction, such as a `mouseup` or a `pointerup` event). It expands from the center. | ||
`layout() => void` | Recomputes all dimensions and positions for the ripple element. Useful if a ripple surface's position or dimension is changed programmatically. | ||
`setUnbounded(unbounded: boolean) => void` | Sets the ripple to be unbounded or not, based on the given boolean. | ||
Recomputes all dimensions and positions for the ripple element. Useful if a ripple surface's | ||
position or dimension is changed programmatically. | ||
## Tips/Tricks | ||
### Unbounded Ripples | ||
### Using a sentinel element for a ripple | ||
If you'd like to use _unbounded_ ripples, such as those used for checkboxes and radio buttons, you | ||
can do so either imperatively in JS _or_ declaratively using the DOM. | ||
Usually, you'll want to leverage `::before` and `::after` pseudo-elements when integrating the ripple into MDC Web components. If you can't use pseudo-elements, create a sentinel element inside your root element. The sentinel element covers the root element's surface. | ||
```html | ||
<div class="my-component"> | ||
<div class="mdc-ripple-surface"></div> | ||
<!-- your component DOM --> | ||
</div> | ||
``` | ||
### Unbounded ripple | ||
You can set a ripple to be _unbounded_, such as those used for MDC Checkboxes and MDC Radio Buttons, either imperatively in JS _or_ declaratively using the DOM. | ||
#### Using JS | ||
You can set an `unbounded` property to specify whether or not the ripple is unbounded. | ||
Set the `unbounded` property on the `MDCRipple` component. | ||
@@ -192,19 +208,8 @@ ```javascript | ||
If directly using our foundation, you must provide this information directly anyway, so simply have | ||
`isUnbounded` return `true`. | ||
#### Using DOM | ||
```javascript | ||
const foundation = new MDCRippleFoundation({ | ||
isUnbounded: () => true, | ||
// ... | ||
}); | ||
``` | ||
Add a `data-mdc-ripple-is-unbounded` attribute to your root element. | ||
#### Using DOM (Component Only) | ||
If you are using our vanilla component for the ripple (not our foundation class), you can add a | ||
data attribute to your root element indicating that you wish the ripple to be unbounded: | ||
```html | ||
<div class="surface" data-mdc-ripple-is-unbounded> | ||
<div class="my-surface" data-mdc-ripple-is-unbounded> | ||
<p>A surface</p> | ||
@@ -214,65 +219,8 @@ </div> | ||
### The mdc-ripple-surface class | ||
### MDCRipple with custom functionality | ||
mdc-ripple contains CSS which exports an `mdc-ripple-surface` class that can turn any element into | ||
a ripple: | ||
Usually, you'll want to use `MDCRipple` _along_ with the component for the actual UI element you're trying to add a | ||
ripple to. `MDCRipple` has a static `createAdapter(instance)` method that can be used to instantiate a ripple within | ||
any `MDCComponent` that requires custom adapter functionality. | ||
```html | ||
<style> | ||
.my-surface { | ||
width: 200px; | ||
height: 200px; | ||
background: grey; /* Google Blue 500 :) */ | ||
border-radius: 2px; | ||
} | ||
</style> | ||
<!-- ... --> | ||
<div class="mdc-ripple-surface my-surface" tabindex="0">Ripples FTW!</div> | ||
``` | ||
There are also modifier classes that can be used for styling ripple surfaces using the configured | ||
theme's primary and secondary colors | ||
```html | ||
<div class="mdc-ripple-surface mdc-ripple-surface--primary my-surface" tabindex="0"> | ||
Surface with a primary-colored ripple. | ||
</div> | ||
<div class="mdc-ripple-surface mdc-ripple-surface--accent my-surface" tabindex="0"> | ||
Surface with a secondary-colored ripple. | ||
</div> | ||
``` | ||
Check out our demo (in the top-level `demos/` directory) to see these classes in action. | ||
### Using the foundation | ||
The MDCRippleFoundation can be used like any other foundation component. Usually, you'll want to use | ||
it in your component _along_ with the foundation for the actual UI element you're trying to add a | ||
ripple to. The adapter API is as follows: | ||
| Method Signature | Description | | ||
| --- | --- | | ||
| `browserSupportsCssVars() => boolean` | Whether or not the given browser supports CSS Variables. When implementing this, please take the [Edge](#caveat-edge) and [Safari 9](#caveat-safari) considerations into account. We provide a `supportsCssVariables` function within the `util.js` which we recommend using, as it handles this for you. | | ||
| `isUnbounded() => boolean` | Whether or not the ripple should be considered unbounded. | | ||
| `setUnbounded(unbounded: boolean) => void` | Adds the unbounded class when truthy, removes when falsy | | ||
| `isSurfaceActive() => boolean` | Whether or not the surface the ripple is acting upon is [active](https://www.w3.org/TR/css3-selectors/#useraction-pseudos). We use this to detect whether or not a keyboard event has activated the surface the ripple is on. This does not need to make use of `:active` (which is what we do); feel free to supply your own heuristics for it. | | ||
| `isSurfaceDisabled() => boolean` | Whether or not the ripple is attached to a disabled component. If true, the ripple will not activate. | | ||
| `addClass(className: string) => void` | Adds a class to the ripple surface | | ||
| `removeClass(className: string) => void` | Removes a class from the ripple surface | | ||
| `registerInteractionHandler(evtType: string, handler: EventListener) => void` | Registers an event handler that's invoked when the ripple is interacted with using type `evtType`. Essentially equivalent to `HTMLElement.prototype.addEventListener`. | | ||
| `deregisterInteractionHandler(evtType: string, handler: EventListener) => void` | Unregisters an event handler that's invoked when the ripple is interacted with using type `evtType`. Essentially equivalent to `HTMLElement.prototype.removeEventListener`. | | ||
| `registerDocumentInteractionHandler(evtType: string, handler: EventListener) => void` | Registers an event handler that's invoked when the documentElement is interacted with using type `evtType` | | ||
| `deregisterDocumentInteractionHandler(evtType: string, handler: EventListener) => void` | Unregisters an event handler that's invoked when the documentElement is interacted with using type `evtType` | | ||
| `registerResizeHandler(handler: Function) => void` | Registers a handler to be called when the surface (or its viewport) resizes. Our default implementation adds the handler as a listener to the window's `resize()` event. | | ||
| `deregisterResizeHandler(handler: Function) => void` | Unregisters a handler to be called when the surface (or its viewport) resizes. Our default implementation removes the handler as a listener to the window's `resize()` event. | | ||
| `updateCssVariable(varName: string, value: (string or null)) => void` | Programmatically sets the css variable `varName` on the surface to the value specified. | | ||
| `computeBoundingRect() => ClientRect` | Returns the ClientRect for the surface. | | ||
| `getWindowPageOffset() => {x: number, y: number}` | Returns the `page{X,Y}Offset` values for the window object as `x` and `y` properties of an object (respectively). | | ||
### Using the vanilla DOM adapter | ||
Because ripples are used so ubiquitously throughout our codebase, `MDCRipple` has a static | ||
`createAdapter(instance)` method that can be used to instantiate an adapter object that can be used by | ||
any `MDCComponent` that needs to instantiate an `MDCRippleFoundation` with custom functionality. | ||
```js | ||
@@ -282,53 +230,24 @@ class MyMDCComponent extends MDCComponent { | ||
super(...arguments); | ||
this.ripple_ = new MDCRippleFoundation(Object.assign(MDCRipple.createAdapter(this), { | ||
isSurfaceActive: () => this.isActive_ | ||
const foundation = new MDCRippleFoundation(Object.assign(MDCRipple.createAdapter(this), { | ||
isSurfaceActive: () => this.isActive_, /* Custom functionality */ | ||
})); | ||
this.ripple_.init(); | ||
this.ripple = new MDCRipple(this.root, foundation); | ||
} | ||
// ... | ||
} | ||
``` | ||
## Tips/Tricks | ||
### Handling keyboard events for custom UI components | ||
### Integrating ripples into MDC Web components | ||
Different keyboard events activate different elements. For example, the space key activates buttons, while the enter key activates links. | ||
Usually, you'll want to leverage `::before` and `::after` pseudo-elements when integrating the | ||
ripple into MDC Web components. Furthermore, when defining your component, you can instantiate the | ||
ripple foundation at the top level, and share logic between those adapters. | ||
`MDCRipple` uses the `adapter.isSurfaceActive()` method to detect whether or not a keyboard event has activated the surface the ripple is on. Our vanilla implementation of the adapter does this by checking whether the `:active` pseudo-class has been applied to the ripple surface. However, this approach will _not_ work for custom components that the browser does not apply this pseudo-class to. | ||
### Using a sentinel element for a ripple | ||
To make your component work properly with keyboard events, you'll have to listen for both `keydown` and `keyup` events to set some state that determines whether or not the surface is "active". | ||
If you find you can't use pseudo-elements to style the ripple, another strategy could be to use a | ||
sentinel element that goes inside your element and covers its surface. Doing this should get you | ||
the same effect. | ||
```html | ||
<div class="my-component"> | ||
<div class="mdc-ripple-surface"></div> | ||
<!-- your component DOM --> | ||
</div> | ||
``` | ||
### Keyboard interaction for custom UI components | ||
Different keyboard events activate different elements. For example, the space key activate buttons, while the enter key activates links. Handling this by sniffing the key/keyCode of an event is brittle and error-prone, so instead we take the approach of using `adapter.isSurfaceActive()`. The | ||
way in which our default vanilla DOM adapter determines this is by using | ||
`element.matches(':active')`. However, this approach will _not_ work for custom components that | ||
the browser does not apply this pseudo-class to. | ||
If you want your component to work properly with keyboard events, you'll have to listen for both `keydown` and `keyup` and set some sort of state that the adapter can use to determine whether or | ||
not the surface is "active", e.g. | ||
```js | ||
class MyComponent { | ||
constructor(el) { | ||
this.el = el; | ||
constructor(element) { | ||
this.root = element; | ||
this.active = false; | ||
this.ripple_ = new MDCRippleFoundation({ | ||
// ... | ||
isSurfaceActive: () => this.active | ||
}); | ||
this.el.addEventListener('keydown', evt => { | ||
this.root.addEventListener('keydown', evt => { | ||
if (isSpace(evt)) { | ||
@@ -338,3 +257,3 @@ this.active = true; | ||
}); | ||
this.el.addEventListener('keyup', evt => { | ||
this.root.addEventListener('keyup', evt => { | ||
if (isSpace(evt)) { | ||
@@ -344,2 +263,8 @@ this.active = false; | ||
}); | ||
const foundation = new MDCRippleFoundation(Object.assign(MDCRipple.createAdapter(this), { | ||
// ... | ||
isSurfaceActive: () => this.active | ||
})); | ||
this.ripple = new MDCRipple(this.root, foundation); | ||
} | ||
@@ -349,15 +274,9 @@ } | ||
### Specifying known element dimensions | ||
### Specifying known element dimensions for asynchronous style loading | ||
If you asynchronously load style resources, such as loading stylesheets dynamically via scripts | ||
or loading fonts, then `adapter.getClientRect()` may by default return _incorrect_ dimensions when | ||
the ripple foundation is initialized. For example, if you put a ripple on an element that uses an | ||
icon font, and the size of the icon font isn't specified at initialization time, then if that icon | ||
font hasn't loaded it may report the intrinsic width/height incorrectly. In order to prevent this, | ||
you can override the default behavior of `getClientRect()` to return the correct results. For | ||
example, if you know an icon font sizes its elements to `24px` width/height, you can do the | ||
following: | ||
If you asynchronously load style resources, such as loading stylesheets dynamically or loading fonts, then `adapter.getClientRect()` may return _incorrect_ dimensions if the ripple is initialized before the stylesheet/font has loaded. In this case, you can override the default behavior of `getClientRect()` to return the correct results. | ||
For example, if you know an icon font sizes its elements to `24px` width and height: | ||
```js | ||
this.ripple_ = new MDCRippleFoundation({ | ||
const foundation = new MDCRippleFoundation({ | ||
// ... | ||
@@ -377,6 +296,22 @@ computeBoundingRect: () => { | ||
}); | ||
this.ripple = new MDCRipple(this.root, foundation); | ||
``` | ||
## Caveat: Edge | ||
### The util API | ||
External frameworks and libraries can use the following utility methods when integrating a component. | ||
Method Signature | Description | ||
--- | --- | ||
`util.supportsCssVariables(windowObj, forceRefresh = false) => Boolean` | Determine whether the current browser supports CSS variables (custom properties) | ||
`util.applyPassive(globalObj = window, forceRefresh = false) => object` | Determine whether the current browser supports passive event listeners | ||
`util.getMatchesProperty(HTMLElementPrototype) => Function` | Return the correct "matches" property to use on the current browser | ||
`util.getNormalizedEventCoords(ev, pageOffset, clientRect) => object` | Determines X/Y coordinates of an event normalized for touch events and ripples | ||
> _NOTE_: The functions `util.supportsCssVariables` and `util.applyPassive` cache their results; `forceRefresh` will force recomputation, but is used mainly for testing and should not be necessary in normal use. | ||
## Caveats | ||
### Caveat: Edge | ||
> TL;DR ripples are disabled in Edge because of issues with its support of CSS variables in pseudo elements. | ||
@@ -386,24 +321,15 @@ | ||
[known issues](https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/11495448/) | ||
involving its implementation for pseudo-elements which cause ripples to behave incorrectly. | ||
involving its implementation for pseudo-elements, which cause ripples to behave incorrectly. | ||
We feature-detect Edge's buggy behavior as it pertains to `::before`, and do not initialize ripples if the bug is | ||
observed. Earlier versions of Edge (and IE) are not affected, as they do not report support for CSS variables at all, | ||
observed. Earlier versions of Edge (and IE) do not support CSS variables at all, | ||
and as such ripples are never initialized. | ||
<a name="caveat-safari"></a> | ||
## Caveat: Safari 9 | ||
### Caveat: Safari 9 | ||
> TL;DR ripples are disabled in Safari 9 because of a nasty CSS variables bug. | ||
> TL;DR ripples are disabled in Safari 9 because of a bug with CSS variables. | ||
The ripple works by updating CSS Variables which are used by pseudo-elements. This allows ripple | ||
effects to work on elements without the need to add a bunch of extra DOM to them. Unfortunately, in | ||
Safari 9.1, there is a nasty bug where updating a css variable on an element will _not_ trigger a | ||
style recalculation on that element's pseudo-elements which make use of the css variable (try out | ||
[this codepen](http://codepen.io/traviskaufman/pen/jARYOR) in Chrome, and then in Safari 9.1 to | ||
see the issue). We feature-detect around this using alternative heuristics regarding different | ||
webkit versions: Webkit builds which have this bug fixed (e.g. the builds used in Safari 10+) | ||
support [CSS 4 Hex Notation](https://drafts.csswg.org/css-color/#hex-notation) while those do not | ||
have the fix don't. We use this to reliably feature-detect whether we are working with a WebKit | ||
build that can handle our usage of CSS variables. | ||
The ripple works by updating CSS variables used by pseudo-elements. Unfortunately, in Safari 9.1, there is a bug where updating a CSS variable on an element will _not_ trigger a style recalculation on that element's pseudo-elements (try out [this codepen](http://codepen.io/traviskaufman/pen/jARYOR) in Chrome, and then in Safari 9.1 to see the issue). Webkit builds which have this bug fixed (e.g. the builds used in Safari 10+) | ||
support [CSS 4 Hex Notation](https://drafts.csswg.org/css-color/#hex-notation) while those without the fix don't. We feature-detect whether we are working with a WebKit build that can handle our usage of CSS variables. | ||
## Caveat: Mobile Safari | ||
### Caveat: Mobile Safari | ||
@@ -418,3 +344,3 @@ > TL;DR for CSS-only ripple styles to work as intended, register a `touchstart` event handler on the affected element or its ancestor. | ||
## Caveat: Theme Custom Variables | ||
### Caveat: Theme Custom Variables | ||
@@ -424,4 +350,4 @@ > TL;DR theme custom variable changes will not propagate to ripples if the browser does not support | ||
The way that [mdc-theme works](../mdc-theme#mdc-theme-prop-mixin) is that it emits two properties: one with the hard-coded sass variable, and another for a | ||
CSS variable that can be interpolated. The problem is that ripple backgrounds need to have an opacity, and currently there's no way to opacify a pre-existing color defined by a CSS variable. | ||
[MDC Theme](../mdc-theme#mdc-theme-prop-mixin) works by emitting two properties: one with the hard-coded Sass variable, and another for a | ||
CSS variable that can be interpolated. Ripple backgrounds need to have an opacity, and currently there's no way to opacify a pre-existing color defined by a CSS variable. | ||
There is an editor's draft for a `color-mod` function (see link in TL;DR) that _can_ do this: | ||
@@ -433,24 +359,2 @@ | ||
But as far as we know, no browsers yet support it. We have added a `@supports` clause into our code | ||
to make sure that it can be used as soon as browsers adopt it, but for now this means that _changes | ||
to your theme via a custom variable will not propagate to ripples._ We don't see this being a gigantic issue as we envision most users configuring one theme via sass. For places where you do need this, special treatment will have to be given. | ||
### The util API | ||
External frameworks and libraries can use the following utility methods when integrating a component. | ||
#### util.supportsCssVariables(windowObj, forceRefresh = false) => Boolean | ||
Determine whether the current browser supports CSS variables (custom properties). This function caches its result; `forceRefresh` will force recomputation, but is used mainly for testing and should not be necessary in normal use. | ||
#### util.applyPassive(globalObj = window, forceRefresh = false) => object | ||
Determine whether the current browser supports passive event listeners, and if so, use them. This function caches its result; `forceRefresh` will force recomputation, but is used mainly for testing and should not be necessary in normal use. | ||
#### getMatchesProperty(HTMLElementPrototype) => Function | ||
Choose the correct matches property to use on the current browser. | ||
#### getNormalizedEventCoords(ev, pageOffset, clientRect) => object | ||
Determines X/Y coordinates of an event normalized for touch events and ripples. | ||
But as far as we know, no browsers yet support it. We have added a `@supports` clause into our code to make sure that it can be used as soon as browsers adopt it, but for now this means that _changes to your theme via a custom variable will not propagate to ripples._ For places where you do need this, special treatment will have to be given. |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
160390
2591
346
+ Added@material/theme@0.30.0(transitive)
- Removed@material/theme@0.29.0(transitive)
Updated@material/theme@^0.30.0