foundation.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. /**
  2. * @license
  3. * Copyright 2016 Google Inc.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. */
  23. import * as tslib_1 from "tslib";
  24. import { MDCFoundation } from '@material/base/foundation';
  25. import { cssClasses, numbers, strings } from './constants';
  26. import { getNormalizedEventCoords } from './util';
  27. // Activation events registered on the root element of each instance for activation
  28. var ACTIVATION_EVENT_TYPES = [
  29. 'touchstart', 'pointerdown', 'mousedown', 'keydown',
  30. ];
  31. // Deactivation events registered on documentElement when a pointer-related down event occurs
  32. var POINTER_DEACTIVATION_EVENT_TYPES = [
  33. 'touchend', 'pointerup', 'mouseup', 'contextmenu',
  34. ];
  35. // simultaneous nested activations
  36. var activatedTargets = [];
  37. var MDCRippleFoundation = /** @class */ (function (_super) {
  38. tslib_1.__extends(MDCRippleFoundation, _super);
  39. function MDCRippleFoundation(adapter) {
  40. var _this = _super.call(this, tslib_1.__assign({}, MDCRippleFoundation.defaultAdapter, adapter)) || this;
  41. _this.activationAnimationHasEnded_ = false;
  42. _this.activationTimer_ = 0;
  43. _this.fgDeactivationRemovalTimer_ = 0;
  44. _this.fgScale_ = '0';
  45. _this.frame_ = { width: 0, height: 0 };
  46. _this.initialSize_ = 0;
  47. _this.layoutFrame_ = 0;
  48. _this.maxRadius_ = 0;
  49. _this.unboundedCoords_ = { left: 0, top: 0 };
  50. _this.activationState_ = _this.defaultActivationState_();
  51. _this.activationTimerCallback_ = function () {
  52. _this.activationAnimationHasEnded_ = true;
  53. _this.runDeactivationUXLogicIfReady_();
  54. };
  55. _this.activateHandler_ = function (e) { return _this.activate_(e); };
  56. _this.deactivateHandler_ = function () { return _this.deactivate_(); };
  57. _this.focusHandler_ = function () { return _this.handleFocus(); };
  58. _this.blurHandler_ = function () { return _this.handleBlur(); };
  59. _this.resizeHandler_ = function () { return _this.layout(); };
  60. return _this;
  61. }
  62. Object.defineProperty(MDCRippleFoundation, "cssClasses", {
  63. get: function () {
  64. return cssClasses;
  65. },
  66. enumerable: true,
  67. configurable: true
  68. });
  69. Object.defineProperty(MDCRippleFoundation, "strings", {
  70. get: function () {
  71. return strings;
  72. },
  73. enumerable: true,
  74. configurable: true
  75. });
  76. Object.defineProperty(MDCRippleFoundation, "numbers", {
  77. get: function () {
  78. return numbers;
  79. },
  80. enumerable: true,
  81. configurable: true
  82. });
  83. Object.defineProperty(MDCRippleFoundation, "defaultAdapter", {
  84. get: function () {
  85. return {
  86. addClass: function () { return undefined; },
  87. browserSupportsCssVars: function () { return true; },
  88. computeBoundingRect: function () { return ({ top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 }); },
  89. containsEventTarget: function () { return true; },
  90. deregisterDocumentInteractionHandler: function () { return undefined; },
  91. deregisterInteractionHandler: function () { return undefined; },
  92. deregisterResizeHandler: function () { return undefined; },
  93. getWindowPageOffset: function () { return ({ x: 0, y: 0 }); },
  94. isSurfaceActive: function () { return true; },
  95. isSurfaceDisabled: function () { return true; },
  96. isUnbounded: function () { return true; },
  97. registerDocumentInteractionHandler: function () { return undefined; },
  98. registerInteractionHandler: function () { return undefined; },
  99. registerResizeHandler: function () { return undefined; },
  100. removeClass: function () { return undefined; },
  101. updateCssVariable: function () { return undefined; },
  102. };
  103. },
  104. enumerable: true,
  105. configurable: true
  106. });
  107. MDCRippleFoundation.prototype.init = function () {
  108. var _this = this;
  109. var supportsPressRipple = this.supportsPressRipple_();
  110. this.registerRootHandlers_(supportsPressRipple);
  111. if (supportsPressRipple) {
  112. var _a = MDCRippleFoundation.cssClasses, ROOT_1 = _a.ROOT, UNBOUNDED_1 = _a.UNBOUNDED;
  113. requestAnimationFrame(function () {
  114. _this.adapter_.addClass(ROOT_1);
  115. if (_this.adapter_.isUnbounded()) {
  116. _this.adapter_.addClass(UNBOUNDED_1);
  117. // Unbounded ripples need layout logic applied immediately to set coordinates for both shade and ripple
  118. _this.layoutInternal_();
  119. }
  120. });
  121. }
  122. };
  123. MDCRippleFoundation.prototype.destroy = function () {
  124. var _this = this;
  125. if (this.supportsPressRipple_()) {
  126. if (this.activationTimer_) {
  127. clearTimeout(this.activationTimer_);
  128. this.activationTimer_ = 0;
  129. this.adapter_.removeClass(MDCRippleFoundation.cssClasses.FG_ACTIVATION);
  130. }
  131. if (this.fgDeactivationRemovalTimer_) {
  132. clearTimeout(this.fgDeactivationRemovalTimer_);
  133. this.fgDeactivationRemovalTimer_ = 0;
  134. this.adapter_.removeClass(MDCRippleFoundation.cssClasses.FG_DEACTIVATION);
  135. }
  136. var _a = MDCRippleFoundation.cssClasses, ROOT_2 = _a.ROOT, UNBOUNDED_2 = _a.UNBOUNDED;
  137. requestAnimationFrame(function () {
  138. _this.adapter_.removeClass(ROOT_2);
  139. _this.adapter_.removeClass(UNBOUNDED_2);
  140. _this.removeCssVars_();
  141. });
  142. }
  143. this.deregisterRootHandlers_();
  144. this.deregisterDeactivationHandlers_();
  145. };
  146. /**
  147. * @param evt Optional event containing position information.
  148. */
  149. MDCRippleFoundation.prototype.activate = function (evt) {
  150. this.activate_(evt);
  151. };
  152. MDCRippleFoundation.prototype.deactivate = function () {
  153. this.deactivate_();
  154. };
  155. MDCRippleFoundation.prototype.layout = function () {
  156. var _this = this;
  157. if (this.layoutFrame_) {
  158. cancelAnimationFrame(this.layoutFrame_);
  159. }
  160. this.layoutFrame_ = requestAnimationFrame(function () {
  161. _this.layoutInternal_();
  162. _this.layoutFrame_ = 0;
  163. });
  164. };
  165. MDCRippleFoundation.prototype.setUnbounded = function (unbounded) {
  166. var UNBOUNDED = MDCRippleFoundation.cssClasses.UNBOUNDED;
  167. if (unbounded) {
  168. this.adapter_.addClass(UNBOUNDED);
  169. }
  170. else {
  171. this.adapter_.removeClass(UNBOUNDED);
  172. }
  173. };
  174. MDCRippleFoundation.prototype.handleFocus = function () {
  175. var _this = this;
  176. requestAnimationFrame(function () {
  177. return _this.adapter_.addClass(MDCRippleFoundation.cssClasses.BG_FOCUSED);
  178. });
  179. };
  180. MDCRippleFoundation.prototype.handleBlur = function () {
  181. var _this = this;
  182. requestAnimationFrame(function () {
  183. return _this.adapter_.removeClass(MDCRippleFoundation.cssClasses.BG_FOCUSED);
  184. });
  185. };
  186. /**
  187. * We compute this property so that we are not querying information about the client
  188. * until the point in time where the foundation requests it. This prevents scenarios where
  189. * client-side feature-detection may happen too early, such as when components are rendered on the server
  190. * and then initialized at mount time on the client.
  191. */
  192. MDCRippleFoundation.prototype.supportsPressRipple_ = function () {
  193. return this.adapter_.browserSupportsCssVars();
  194. };
  195. MDCRippleFoundation.prototype.defaultActivationState_ = function () {
  196. return {
  197. activationEvent: undefined,
  198. hasDeactivationUXRun: false,
  199. isActivated: false,
  200. isProgrammatic: false,
  201. wasActivatedByPointer: false,
  202. wasElementMadeActive: false,
  203. };
  204. };
  205. /**
  206. * supportsPressRipple Passed from init to save a redundant function call
  207. */
  208. MDCRippleFoundation.prototype.registerRootHandlers_ = function (supportsPressRipple) {
  209. var _this = this;
  210. if (supportsPressRipple) {
  211. ACTIVATION_EVENT_TYPES.forEach(function (evtType) {
  212. _this.adapter_.registerInteractionHandler(evtType, _this.activateHandler_);
  213. });
  214. if (this.adapter_.isUnbounded()) {
  215. this.adapter_.registerResizeHandler(this.resizeHandler_);
  216. }
  217. }
  218. this.adapter_.registerInteractionHandler('focus', this.focusHandler_);
  219. this.adapter_.registerInteractionHandler('blur', this.blurHandler_);
  220. };
  221. MDCRippleFoundation.prototype.registerDeactivationHandlers_ = function (evt) {
  222. var _this = this;
  223. if (evt.type === 'keydown') {
  224. this.adapter_.registerInteractionHandler('keyup', this.deactivateHandler_);
  225. }
  226. else {
  227. POINTER_DEACTIVATION_EVENT_TYPES.forEach(function (evtType) {
  228. _this.adapter_.registerDocumentInteractionHandler(evtType, _this.deactivateHandler_);
  229. });
  230. }
  231. };
  232. MDCRippleFoundation.prototype.deregisterRootHandlers_ = function () {
  233. var _this = this;
  234. ACTIVATION_EVENT_TYPES.forEach(function (evtType) {
  235. _this.adapter_.deregisterInteractionHandler(evtType, _this.activateHandler_);
  236. });
  237. this.adapter_.deregisterInteractionHandler('focus', this.focusHandler_);
  238. this.adapter_.deregisterInteractionHandler('blur', this.blurHandler_);
  239. if (this.adapter_.isUnbounded()) {
  240. this.adapter_.deregisterResizeHandler(this.resizeHandler_);
  241. }
  242. };
  243. MDCRippleFoundation.prototype.deregisterDeactivationHandlers_ = function () {
  244. var _this = this;
  245. this.adapter_.deregisterInteractionHandler('keyup', this.deactivateHandler_);
  246. POINTER_DEACTIVATION_EVENT_TYPES.forEach(function (evtType) {
  247. _this.adapter_.deregisterDocumentInteractionHandler(evtType, _this.deactivateHandler_);
  248. });
  249. };
  250. MDCRippleFoundation.prototype.removeCssVars_ = function () {
  251. var _this = this;
  252. var rippleStrings = MDCRippleFoundation.strings;
  253. var keys = Object.keys(rippleStrings);
  254. keys.forEach(function (key) {
  255. if (key.indexOf('VAR_') === 0) {
  256. _this.adapter_.updateCssVariable(rippleStrings[key], null);
  257. }
  258. });
  259. };
  260. MDCRippleFoundation.prototype.activate_ = function (evt) {
  261. var _this = this;
  262. if (this.adapter_.isSurfaceDisabled()) {
  263. return;
  264. }
  265. var activationState = this.activationState_;
  266. if (activationState.isActivated) {
  267. return;
  268. }
  269. // Avoid reacting to follow-on events fired by touch device after an already-processed user interaction
  270. var previousActivationEvent = this.previousActivationEvent_;
  271. var isSameInteraction = previousActivationEvent && evt !== undefined && previousActivationEvent.type !== evt.type;
  272. if (isSameInteraction) {
  273. return;
  274. }
  275. activationState.isActivated = true;
  276. activationState.isProgrammatic = evt === undefined;
  277. activationState.activationEvent = evt;
  278. activationState.wasActivatedByPointer = activationState.isProgrammatic ? false : evt !== undefined && (evt.type === 'mousedown' || evt.type === 'touchstart' || evt.type === 'pointerdown');
  279. var hasActivatedChild = evt !== undefined && activatedTargets.length > 0 && activatedTargets.some(function (target) { return _this.adapter_.containsEventTarget(target); });
  280. if (hasActivatedChild) {
  281. // Immediately reset activation state, while preserving logic that prevents touch follow-on events
  282. this.resetActivationState_();
  283. return;
  284. }
  285. if (evt !== undefined) {
  286. activatedTargets.push(evt.target);
  287. this.registerDeactivationHandlers_(evt);
  288. }
  289. activationState.wasElementMadeActive = this.checkElementMadeActive_(evt);
  290. if (activationState.wasElementMadeActive) {
  291. this.animateActivation_();
  292. }
  293. requestAnimationFrame(function () {
  294. // Reset array on next frame after the current event has had a chance to bubble to prevent ancestor ripples
  295. activatedTargets = [];
  296. if (!activationState.wasElementMadeActive
  297. && evt !== undefined
  298. && (evt.key === ' ' || evt.keyCode === 32)) {
  299. // If space was pressed, try again within an rAF call to detect :active, because different UAs report
  300. // active states inconsistently when they're called within event handling code:
  301. // - https://bugs.chromium.org/p/chromium/issues/detail?id=635971
  302. // - https://bugzilla.mozilla.org/show_bug.cgi?id=1293741
  303. // We try first outside rAF to support Edge, which does not exhibit this problem, but will crash if a CSS
  304. // variable is set within a rAF callback for a submit button interaction (#2241).
  305. activationState.wasElementMadeActive = _this.checkElementMadeActive_(evt);
  306. if (activationState.wasElementMadeActive) {
  307. _this.animateActivation_();
  308. }
  309. }
  310. if (!activationState.wasElementMadeActive) {
  311. // Reset activation state immediately if element was not made active.
  312. _this.activationState_ = _this.defaultActivationState_();
  313. }
  314. });
  315. };
  316. MDCRippleFoundation.prototype.checkElementMadeActive_ = function (evt) {
  317. return (evt !== undefined && evt.type === 'keydown') ? this.adapter_.isSurfaceActive() : true;
  318. };
  319. MDCRippleFoundation.prototype.animateActivation_ = function () {
  320. var _this = this;
  321. var _a = MDCRippleFoundation.strings, VAR_FG_TRANSLATE_START = _a.VAR_FG_TRANSLATE_START, VAR_FG_TRANSLATE_END = _a.VAR_FG_TRANSLATE_END;
  322. var _b = MDCRippleFoundation.cssClasses, FG_DEACTIVATION = _b.FG_DEACTIVATION, FG_ACTIVATION = _b.FG_ACTIVATION;
  323. var DEACTIVATION_TIMEOUT_MS = MDCRippleFoundation.numbers.DEACTIVATION_TIMEOUT_MS;
  324. this.layoutInternal_();
  325. var translateStart = '';
  326. var translateEnd = '';
  327. if (!this.adapter_.isUnbounded()) {
  328. var _c = this.getFgTranslationCoordinates_(), startPoint = _c.startPoint, endPoint = _c.endPoint;
  329. translateStart = startPoint.x + "px, " + startPoint.y + "px";
  330. translateEnd = endPoint.x + "px, " + endPoint.y + "px";
  331. }
  332. this.adapter_.updateCssVariable(VAR_FG_TRANSLATE_START, translateStart);
  333. this.adapter_.updateCssVariable(VAR_FG_TRANSLATE_END, translateEnd);
  334. // Cancel any ongoing activation/deactivation animations
  335. clearTimeout(this.activationTimer_);
  336. clearTimeout(this.fgDeactivationRemovalTimer_);
  337. this.rmBoundedActivationClasses_();
  338. this.adapter_.removeClass(FG_DEACTIVATION);
  339. // Force layout in order to re-trigger the animation.
  340. this.adapter_.computeBoundingRect();
  341. this.adapter_.addClass(FG_ACTIVATION);
  342. this.activationTimer_ = setTimeout(function () { return _this.activationTimerCallback_(); }, DEACTIVATION_TIMEOUT_MS);
  343. };
  344. MDCRippleFoundation.prototype.getFgTranslationCoordinates_ = function () {
  345. var _a = this.activationState_, activationEvent = _a.activationEvent, wasActivatedByPointer = _a.wasActivatedByPointer;
  346. var startPoint;
  347. if (wasActivatedByPointer) {
  348. startPoint = getNormalizedEventCoords(activationEvent, this.adapter_.getWindowPageOffset(), this.adapter_.computeBoundingRect());
  349. }
  350. else {
  351. startPoint = {
  352. x: this.frame_.width / 2,
  353. y: this.frame_.height / 2,
  354. };
  355. }
  356. // Center the element around the start point.
  357. startPoint = {
  358. x: startPoint.x - (this.initialSize_ / 2),
  359. y: startPoint.y - (this.initialSize_ / 2),
  360. };
  361. var endPoint = {
  362. x: (this.frame_.width / 2) - (this.initialSize_ / 2),
  363. y: (this.frame_.height / 2) - (this.initialSize_ / 2),
  364. };
  365. return { startPoint: startPoint, endPoint: endPoint };
  366. };
  367. MDCRippleFoundation.prototype.runDeactivationUXLogicIfReady_ = function () {
  368. var _this = this;
  369. // This method is called both when a pointing device is released, and when the activation animation ends.
  370. // The deactivation animation should only run after both of those occur.
  371. var FG_DEACTIVATION = MDCRippleFoundation.cssClasses.FG_DEACTIVATION;
  372. var _a = this.activationState_, hasDeactivationUXRun = _a.hasDeactivationUXRun, isActivated = _a.isActivated;
  373. var activationHasEnded = hasDeactivationUXRun || !isActivated;
  374. if (activationHasEnded && this.activationAnimationHasEnded_) {
  375. this.rmBoundedActivationClasses_();
  376. this.adapter_.addClass(FG_DEACTIVATION);
  377. this.fgDeactivationRemovalTimer_ = setTimeout(function () {
  378. _this.adapter_.removeClass(FG_DEACTIVATION);
  379. }, numbers.FG_DEACTIVATION_MS);
  380. }
  381. };
  382. MDCRippleFoundation.prototype.rmBoundedActivationClasses_ = function () {
  383. var FG_ACTIVATION = MDCRippleFoundation.cssClasses.FG_ACTIVATION;
  384. this.adapter_.removeClass(FG_ACTIVATION);
  385. this.activationAnimationHasEnded_ = false;
  386. this.adapter_.computeBoundingRect();
  387. };
  388. MDCRippleFoundation.prototype.resetActivationState_ = function () {
  389. var _this = this;
  390. this.previousActivationEvent_ = this.activationState_.activationEvent;
  391. this.activationState_ = this.defaultActivationState_();
  392. // Touch devices may fire additional events for the same interaction within a short time.
  393. // Store the previous event until it's safe to assume that subsequent events are for new interactions.
  394. setTimeout(function () { return _this.previousActivationEvent_ = undefined; }, MDCRippleFoundation.numbers.TAP_DELAY_MS);
  395. };
  396. MDCRippleFoundation.prototype.deactivate_ = function () {
  397. var _this = this;
  398. var activationState = this.activationState_;
  399. // This can happen in scenarios such as when you have a keyup event that blurs the element.
  400. if (!activationState.isActivated) {
  401. return;
  402. }
  403. var state = tslib_1.__assign({}, activationState);
  404. if (activationState.isProgrammatic) {
  405. requestAnimationFrame(function () { return _this.animateDeactivation_(state); });
  406. this.resetActivationState_();
  407. }
  408. else {
  409. this.deregisterDeactivationHandlers_();
  410. requestAnimationFrame(function () {
  411. _this.activationState_.hasDeactivationUXRun = true;
  412. _this.animateDeactivation_(state);
  413. _this.resetActivationState_();
  414. });
  415. }
  416. };
  417. MDCRippleFoundation.prototype.animateDeactivation_ = function (_a) {
  418. var wasActivatedByPointer = _a.wasActivatedByPointer, wasElementMadeActive = _a.wasElementMadeActive;
  419. if (wasActivatedByPointer || wasElementMadeActive) {
  420. this.runDeactivationUXLogicIfReady_();
  421. }
  422. };
  423. MDCRippleFoundation.prototype.layoutInternal_ = function () {
  424. var _this = this;
  425. this.frame_ = this.adapter_.computeBoundingRect();
  426. var maxDim = Math.max(this.frame_.height, this.frame_.width);
  427. // Surface diameter is treated differently for unbounded vs. bounded ripples.
  428. // Unbounded ripple diameter is calculated smaller since the surface is expected to already be padded appropriately
  429. // to extend the hitbox, and the ripple is expected to meet the edges of the padded hitbox (which is typically
  430. // square). Bounded ripples, on the other hand, are fully expected to expand beyond the surface's longest diameter
  431. // (calculated based on the diagonal plus a constant padding), and are clipped at the surface's border via
  432. // `overflow: hidden`.
  433. var getBoundedRadius = function () {
  434. var hypotenuse = Math.sqrt(Math.pow(_this.frame_.width, 2) + Math.pow(_this.frame_.height, 2));
  435. return hypotenuse + MDCRippleFoundation.numbers.PADDING;
  436. };
  437. this.maxRadius_ = this.adapter_.isUnbounded() ? maxDim : getBoundedRadius();
  438. // Ripple is sized as a fraction of the largest dimension of the surface, then scales up using a CSS scale transform
  439. var initialSize = Math.floor(maxDim * MDCRippleFoundation.numbers.INITIAL_ORIGIN_SCALE);
  440. // Unbounded ripple size should always be even number to equally center align.
  441. if (this.adapter_.isUnbounded() && initialSize % 2 !== 0) {
  442. this.initialSize_ = initialSize - 1;
  443. }
  444. else {
  445. this.initialSize_ = initialSize;
  446. }
  447. this.fgScale_ = "" + this.maxRadius_ / this.initialSize_;
  448. this.updateLayoutCssVars_();
  449. };
  450. MDCRippleFoundation.prototype.updateLayoutCssVars_ = function () {
  451. var _a = MDCRippleFoundation.strings, VAR_FG_SIZE = _a.VAR_FG_SIZE, VAR_LEFT = _a.VAR_LEFT, VAR_TOP = _a.VAR_TOP, VAR_FG_SCALE = _a.VAR_FG_SCALE;
  452. this.adapter_.updateCssVariable(VAR_FG_SIZE, this.initialSize_ + "px");
  453. this.adapter_.updateCssVariable(VAR_FG_SCALE, this.fgScale_);
  454. if (this.adapter_.isUnbounded()) {
  455. this.unboundedCoords_ = {
  456. left: Math.round((this.frame_.width / 2) - (this.initialSize_ / 2)),
  457. top: Math.round((this.frame_.height / 2) - (this.initialSize_ / 2)),
  458. };
  459. this.adapter_.updateCssVariable(VAR_LEFT, this.unboundedCoords_.left + "px");
  460. this.adapter_.updateCssVariable(VAR_TOP, this.unboundedCoords_.top + "px");
  461. }
  462. };
  463. return MDCRippleFoundation;
  464. }(MDCFoundation));
  465. export { MDCRippleFoundation };
  466. // tslint:disable-next-line:no-default-export Needed for backward compatibility with MDC Web v0.44.0 and earlier.
  467. export default MDCRippleFoundation;
  468. //# sourceMappingURL=foundation.js.map