foundation.js 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  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 { __assign, __extends, __values } 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
  28. // activation
  29. var ACTIVATION_EVENT_TYPES = [
  30. 'touchstart',
  31. 'pointerdown',
  32. 'mousedown',
  33. 'keydown',
  34. ];
  35. // Deactivation events registered on documentElement when a pointer-related down
  36. // event occurs
  37. var POINTER_DEACTIVATION_EVENT_TYPES = [
  38. 'touchend',
  39. 'pointerup',
  40. 'mouseup',
  41. 'contextmenu',
  42. ];
  43. // simultaneous nested activations
  44. var activatedTargets = [];
  45. /** MDC Ripple Foundation */
  46. var MDCRippleFoundation = /** @class */ (function (_super) {
  47. __extends(MDCRippleFoundation, _super);
  48. function MDCRippleFoundation(adapter) {
  49. var _this = _super.call(this, __assign(__assign({}, MDCRippleFoundation.defaultAdapter), adapter)) || this;
  50. _this.activationAnimationHasEnded = false;
  51. _this.activationTimer = 0;
  52. _this.fgDeactivationRemovalTimer = 0;
  53. _this.fgScale = '0';
  54. _this.frame = { width: 0, height: 0 };
  55. _this.initialSize = 0;
  56. _this.layoutFrame = 0;
  57. _this.maxRadius = 0;
  58. _this.unboundedCoords = { left: 0, top: 0 };
  59. _this.activationState = _this.defaultActivationState();
  60. _this.activationTimerCallback = function () {
  61. _this.activationAnimationHasEnded = true;
  62. _this.runDeactivationUXLogicIfReady();
  63. };
  64. _this.activateHandler = function (e) {
  65. _this.activateImpl(e);
  66. };
  67. _this.deactivateHandler = function () {
  68. _this.deactivateImpl();
  69. };
  70. _this.focusHandler = function () {
  71. _this.handleFocus();
  72. };
  73. _this.blurHandler = function () {
  74. _this.handleBlur();
  75. };
  76. _this.resizeHandler = function () {
  77. _this.layout();
  78. };
  79. return _this;
  80. }
  81. Object.defineProperty(MDCRippleFoundation, "cssClasses", {
  82. get: function () {
  83. return cssClasses;
  84. },
  85. enumerable: false,
  86. configurable: true
  87. });
  88. Object.defineProperty(MDCRippleFoundation, "strings", {
  89. get: function () {
  90. return strings;
  91. },
  92. enumerable: false,
  93. configurable: true
  94. });
  95. Object.defineProperty(MDCRippleFoundation, "numbers", {
  96. get: function () {
  97. return numbers;
  98. },
  99. enumerable: false,
  100. configurable: true
  101. });
  102. Object.defineProperty(MDCRippleFoundation, "defaultAdapter", {
  103. get: function () {
  104. return {
  105. addClass: function () { return undefined; },
  106. browserSupportsCssVars: function () { return true; },
  107. computeBoundingRect: function () {
  108. return ({ top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 });
  109. },
  110. containsEventTarget: function () { return true; },
  111. deregisterDocumentInteractionHandler: function () { return undefined; },
  112. deregisterInteractionHandler: function () { return undefined; },
  113. deregisterResizeHandler: function () { return undefined; },
  114. getWindowPageOffset: function () { return ({ x: 0, y: 0 }); },
  115. isSurfaceActive: function () { return true; },
  116. isSurfaceDisabled: function () { return true; },
  117. isUnbounded: function () { return true; },
  118. registerDocumentInteractionHandler: function () { return undefined; },
  119. registerInteractionHandler: function () { return undefined; },
  120. registerResizeHandler: function () { return undefined; },
  121. removeClass: function () { return undefined; },
  122. updateCssVariable: function () { return undefined; },
  123. };
  124. },
  125. enumerable: false,
  126. configurable: true
  127. });
  128. MDCRippleFoundation.prototype.init = function () {
  129. var _this = this;
  130. var supportsPressRipple = this.supportsPressRipple();
  131. this.registerRootHandlers(supportsPressRipple);
  132. if (supportsPressRipple) {
  133. var _a = MDCRippleFoundation.cssClasses, ROOT_1 = _a.ROOT, UNBOUNDED_1 = _a.UNBOUNDED;
  134. requestAnimationFrame(function () {
  135. _this.adapter.addClass(ROOT_1);
  136. if (_this.adapter.isUnbounded()) {
  137. _this.adapter.addClass(UNBOUNDED_1);
  138. // Unbounded ripples need layout logic applied immediately to set
  139. // coordinates for both shade and ripple
  140. _this.layoutInternal();
  141. }
  142. });
  143. }
  144. };
  145. MDCRippleFoundation.prototype.destroy = function () {
  146. var _this = this;
  147. if (this.supportsPressRipple()) {
  148. if (this.activationTimer) {
  149. clearTimeout(this.activationTimer);
  150. this.activationTimer = 0;
  151. this.adapter.removeClass(MDCRippleFoundation.cssClasses.FG_ACTIVATION);
  152. }
  153. if (this.fgDeactivationRemovalTimer) {
  154. clearTimeout(this.fgDeactivationRemovalTimer);
  155. this.fgDeactivationRemovalTimer = 0;
  156. this.adapter.removeClass(MDCRippleFoundation.cssClasses.FG_DEACTIVATION);
  157. }
  158. var _a = MDCRippleFoundation.cssClasses, ROOT_2 = _a.ROOT, UNBOUNDED_2 = _a.UNBOUNDED;
  159. requestAnimationFrame(function () {
  160. _this.adapter.removeClass(ROOT_2);
  161. _this.adapter.removeClass(UNBOUNDED_2);
  162. _this.removeCssVars();
  163. });
  164. }
  165. this.deregisterRootHandlers();
  166. this.deregisterDeactivationHandlers();
  167. };
  168. /**
  169. * @param evt Optional event containing position information.
  170. */
  171. MDCRippleFoundation.prototype.activate = function (evt) {
  172. this.activateImpl(evt);
  173. };
  174. MDCRippleFoundation.prototype.deactivate = function () {
  175. this.deactivateImpl();
  176. };
  177. MDCRippleFoundation.prototype.layout = function () {
  178. var _this = this;
  179. if (this.layoutFrame) {
  180. cancelAnimationFrame(this.layoutFrame);
  181. }
  182. this.layoutFrame = requestAnimationFrame(function () {
  183. _this.layoutInternal();
  184. _this.layoutFrame = 0;
  185. });
  186. };
  187. MDCRippleFoundation.prototype.setUnbounded = function (unbounded) {
  188. var UNBOUNDED = MDCRippleFoundation.cssClasses.UNBOUNDED;
  189. if (unbounded) {
  190. this.adapter.addClass(UNBOUNDED);
  191. }
  192. else {
  193. this.adapter.removeClass(UNBOUNDED);
  194. }
  195. };
  196. MDCRippleFoundation.prototype.handleFocus = function () {
  197. var _this = this;
  198. requestAnimationFrame(function () {
  199. _this.adapter.addClass(MDCRippleFoundation.cssClasses.BG_FOCUSED);
  200. });
  201. };
  202. MDCRippleFoundation.prototype.handleBlur = function () {
  203. var _this = this;
  204. requestAnimationFrame(function () {
  205. _this.adapter.removeClass(MDCRippleFoundation.cssClasses.BG_FOCUSED);
  206. });
  207. };
  208. /**
  209. * We compute this property so that we are not querying information about the
  210. * client until the point in time where the foundation requests it. This
  211. * prevents scenarios where client-side feature-detection may happen too
  212. * early, such as when components are rendered on the server and then
  213. * initialized at mount time on the client.
  214. */
  215. MDCRippleFoundation.prototype.supportsPressRipple = function () {
  216. return this.adapter.browserSupportsCssVars();
  217. };
  218. MDCRippleFoundation.prototype.defaultActivationState = function () {
  219. return {
  220. activationEvent: undefined,
  221. hasDeactivationUXRun: false,
  222. isActivated: false,
  223. isProgrammatic: false,
  224. wasActivatedByPointer: false,
  225. wasElementMadeActive: false,
  226. };
  227. };
  228. /**
  229. * supportsPressRipple Passed from init to save a redundant function call
  230. */
  231. MDCRippleFoundation.prototype.registerRootHandlers = function (supportsPressRipple) {
  232. var e_1, _a;
  233. if (supportsPressRipple) {
  234. try {
  235. for (var ACTIVATION_EVENT_TYPES_1 = __values(ACTIVATION_EVENT_TYPES), ACTIVATION_EVENT_TYPES_1_1 = ACTIVATION_EVENT_TYPES_1.next(); !ACTIVATION_EVENT_TYPES_1_1.done; ACTIVATION_EVENT_TYPES_1_1 = ACTIVATION_EVENT_TYPES_1.next()) {
  236. var evtType = ACTIVATION_EVENT_TYPES_1_1.value;
  237. this.adapter.registerInteractionHandler(evtType, this.activateHandler);
  238. }
  239. }
  240. catch (e_1_1) { e_1 = { error: e_1_1 }; }
  241. finally {
  242. try {
  243. if (ACTIVATION_EVENT_TYPES_1_1 && !ACTIVATION_EVENT_TYPES_1_1.done && (_a = ACTIVATION_EVENT_TYPES_1.return)) _a.call(ACTIVATION_EVENT_TYPES_1);
  244. }
  245. finally { if (e_1) throw e_1.error; }
  246. }
  247. if (this.adapter.isUnbounded()) {
  248. this.adapter.registerResizeHandler(this.resizeHandler);
  249. }
  250. }
  251. this.adapter.registerInteractionHandler('focus', this.focusHandler);
  252. this.adapter.registerInteractionHandler('blur', this.blurHandler);
  253. };
  254. MDCRippleFoundation.prototype.registerDeactivationHandlers = function (evt) {
  255. var e_2, _a;
  256. if (evt.type === 'keydown') {
  257. this.adapter.registerInteractionHandler('keyup', this.deactivateHandler);
  258. }
  259. else {
  260. try {
  261. for (var POINTER_DEACTIVATION_EVENT_TYPES_1 = __values(POINTER_DEACTIVATION_EVENT_TYPES), POINTER_DEACTIVATION_EVENT_TYPES_1_1 = POINTER_DEACTIVATION_EVENT_TYPES_1.next(); !POINTER_DEACTIVATION_EVENT_TYPES_1_1.done; POINTER_DEACTIVATION_EVENT_TYPES_1_1 = POINTER_DEACTIVATION_EVENT_TYPES_1.next()) {
  262. var evtType = POINTER_DEACTIVATION_EVENT_TYPES_1_1.value;
  263. this.adapter.registerDocumentInteractionHandler(evtType, this.deactivateHandler);
  264. }
  265. }
  266. catch (e_2_1) { e_2 = { error: e_2_1 }; }
  267. finally {
  268. try {
  269. if (POINTER_DEACTIVATION_EVENT_TYPES_1_1 && !POINTER_DEACTIVATION_EVENT_TYPES_1_1.done && (_a = POINTER_DEACTIVATION_EVENT_TYPES_1.return)) _a.call(POINTER_DEACTIVATION_EVENT_TYPES_1);
  270. }
  271. finally { if (e_2) throw e_2.error; }
  272. }
  273. }
  274. };
  275. MDCRippleFoundation.prototype.deregisterRootHandlers = function () {
  276. var e_3, _a;
  277. try {
  278. for (var ACTIVATION_EVENT_TYPES_2 = __values(ACTIVATION_EVENT_TYPES), ACTIVATION_EVENT_TYPES_2_1 = ACTIVATION_EVENT_TYPES_2.next(); !ACTIVATION_EVENT_TYPES_2_1.done; ACTIVATION_EVENT_TYPES_2_1 = ACTIVATION_EVENT_TYPES_2.next()) {
  279. var evtType = ACTIVATION_EVENT_TYPES_2_1.value;
  280. this.adapter.deregisterInteractionHandler(evtType, this.activateHandler);
  281. }
  282. }
  283. catch (e_3_1) { e_3 = { error: e_3_1 }; }
  284. finally {
  285. try {
  286. if (ACTIVATION_EVENT_TYPES_2_1 && !ACTIVATION_EVENT_TYPES_2_1.done && (_a = ACTIVATION_EVENT_TYPES_2.return)) _a.call(ACTIVATION_EVENT_TYPES_2);
  287. }
  288. finally { if (e_3) throw e_3.error; }
  289. }
  290. this.adapter.deregisterInteractionHandler('focus', this.focusHandler);
  291. this.adapter.deregisterInteractionHandler('blur', this.blurHandler);
  292. if (this.adapter.isUnbounded()) {
  293. this.adapter.deregisterResizeHandler(this.resizeHandler);
  294. }
  295. };
  296. MDCRippleFoundation.prototype.deregisterDeactivationHandlers = function () {
  297. var e_4, _a;
  298. this.adapter.deregisterInteractionHandler('keyup', this.deactivateHandler);
  299. try {
  300. for (var POINTER_DEACTIVATION_EVENT_TYPES_2 = __values(POINTER_DEACTIVATION_EVENT_TYPES), POINTER_DEACTIVATION_EVENT_TYPES_2_1 = POINTER_DEACTIVATION_EVENT_TYPES_2.next(); !POINTER_DEACTIVATION_EVENT_TYPES_2_1.done; POINTER_DEACTIVATION_EVENT_TYPES_2_1 = POINTER_DEACTIVATION_EVENT_TYPES_2.next()) {
  301. var evtType = POINTER_DEACTIVATION_EVENT_TYPES_2_1.value;
  302. this.adapter.deregisterDocumentInteractionHandler(evtType, this.deactivateHandler);
  303. }
  304. }
  305. catch (e_4_1) { e_4 = { error: e_4_1 }; }
  306. finally {
  307. try {
  308. if (POINTER_DEACTIVATION_EVENT_TYPES_2_1 && !POINTER_DEACTIVATION_EVENT_TYPES_2_1.done && (_a = POINTER_DEACTIVATION_EVENT_TYPES_2.return)) _a.call(POINTER_DEACTIVATION_EVENT_TYPES_2);
  309. }
  310. finally { if (e_4) throw e_4.error; }
  311. }
  312. };
  313. MDCRippleFoundation.prototype.removeCssVars = function () {
  314. var _this = this;
  315. var rippleStrings = MDCRippleFoundation.strings;
  316. var keys = Object.keys(rippleStrings);
  317. keys.forEach(function (key) {
  318. if (key.indexOf('VAR_') === 0) {
  319. _this.adapter.updateCssVariable(rippleStrings[key], null);
  320. }
  321. });
  322. };
  323. MDCRippleFoundation.prototype.activateImpl = function (evt) {
  324. var _this = this;
  325. if (this.adapter.isSurfaceDisabled()) {
  326. return;
  327. }
  328. var activationState = this.activationState;
  329. if (activationState.isActivated) {
  330. return;
  331. }
  332. // Avoid reacting to follow-on events fired by touch device after an
  333. // already-processed user interaction
  334. var previousActivationEvent = this.previousActivationEvent;
  335. var isSameInteraction = previousActivationEvent && evt !== undefined &&
  336. previousActivationEvent.type !== evt.type;
  337. if (isSameInteraction) {
  338. return;
  339. }
  340. activationState.isActivated = true;
  341. activationState.isProgrammatic = evt === undefined;
  342. activationState.activationEvent = evt;
  343. activationState.wasActivatedByPointer = activationState.isProgrammatic ?
  344. false :
  345. evt !== undefined &&
  346. (evt.type === 'mousedown' || evt.type === 'touchstart' ||
  347. evt.type === 'pointerdown');
  348. var hasActivatedChild = evt !== undefined &&
  349. activatedTargets.length > 0 &&
  350. activatedTargets.some(function (target) { return _this.adapter.containsEventTarget(target); });
  351. if (hasActivatedChild) {
  352. // Immediately reset activation state, while preserving logic that
  353. // prevents touch follow-on events
  354. this.resetActivationState();
  355. return;
  356. }
  357. if (evt !== undefined) {
  358. activatedTargets.push(evt.target);
  359. this.registerDeactivationHandlers(evt);
  360. }
  361. activationState.wasElementMadeActive = this.checkElementMadeActive(evt);
  362. if (activationState.wasElementMadeActive) {
  363. this.animateActivation();
  364. }
  365. requestAnimationFrame(function () {
  366. // Reset array on next frame after the current event has had a chance to
  367. // bubble to prevent ancestor ripples
  368. activatedTargets = [];
  369. if (!activationState.wasElementMadeActive && evt !== undefined &&
  370. (evt.key === ' ' ||
  371. evt.keyCode === 32)) {
  372. // If space was pressed, try again within an rAF call to detect :active,
  373. // because different UAs report active states inconsistently when
  374. // they're called within event handling code:
  375. // - https://bugs.chromium.org/p/chromium/issues/detail?id=635971
  376. // - https://bugzilla.mozilla.org/show_bug.cgi?id=1293741
  377. // We try first outside rAF to support Edge, which does not exhibit this
  378. // problem, but will crash if a CSS variable is set within a rAF
  379. // callback for a submit button interaction (#2241).
  380. activationState.wasElementMadeActive = _this.checkElementMadeActive(evt);
  381. if (activationState.wasElementMadeActive) {
  382. _this.animateActivation();
  383. }
  384. }
  385. if (!activationState.wasElementMadeActive) {
  386. // Reset activation state immediately if element was not made active.
  387. _this.activationState = _this.defaultActivationState();
  388. }
  389. });
  390. };
  391. MDCRippleFoundation.prototype.checkElementMadeActive = function (evt) {
  392. return (evt !== undefined && evt.type === 'keydown') ?
  393. this.adapter.isSurfaceActive() :
  394. true;
  395. };
  396. MDCRippleFoundation.prototype.animateActivation = function () {
  397. var _this = this;
  398. var _a = MDCRippleFoundation.strings, VAR_FG_TRANSLATE_START = _a.VAR_FG_TRANSLATE_START, VAR_FG_TRANSLATE_END = _a.VAR_FG_TRANSLATE_END;
  399. var _b = MDCRippleFoundation.cssClasses, FG_DEACTIVATION = _b.FG_DEACTIVATION, FG_ACTIVATION = _b.FG_ACTIVATION;
  400. var DEACTIVATION_TIMEOUT_MS = MDCRippleFoundation.numbers.DEACTIVATION_TIMEOUT_MS;
  401. this.layoutInternal();
  402. var translateStart = '';
  403. var translateEnd = '';
  404. if (!this.adapter.isUnbounded()) {
  405. var _c = this.getFgTranslationCoordinates(), startPoint = _c.startPoint, endPoint = _c.endPoint;
  406. translateStart = startPoint.x + "px, " + startPoint.y + "px";
  407. translateEnd = endPoint.x + "px, " + endPoint.y + "px";
  408. }
  409. this.adapter.updateCssVariable(VAR_FG_TRANSLATE_START, translateStart);
  410. this.adapter.updateCssVariable(VAR_FG_TRANSLATE_END, translateEnd);
  411. // Cancel any ongoing activation/deactivation animations
  412. clearTimeout(this.activationTimer);
  413. clearTimeout(this.fgDeactivationRemovalTimer);
  414. this.rmBoundedActivationClasses();
  415. this.adapter.removeClass(FG_DEACTIVATION);
  416. // Force layout in order to re-trigger the animation.
  417. this.adapter.computeBoundingRect();
  418. this.adapter.addClass(FG_ACTIVATION);
  419. this.activationTimer = setTimeout(function () {
  420. _this.activationTimerCallback();
  421. }, DEACTIVATION_TIMEOUT_MS);
  422. };
  423. MDCRippleFoundation.prototype.getFgTranslationCoordinates = function () {
  424. var _a = this.activationState, activationEvent = _a.activationEvent, wasActivatedByPointer = _a.wasActivatedByPointer;
  425. var startPoint;
  426. if (wasActivatedByPointer) {
  427. startPoint = getNormalizedEventCoords(activationEvent, this.adapter.getWindowPageOffset(), this.adapter.computeBoundingRect());
  428. }
  429. else {
  430. startPoint = {
  431. x: this.frame.width / 2,
  432. y: this.frame.height / 2,
  433. };
  434. }
  435. // Center the element around the start point.
  436. startPoint = {
  437. x: startPoint.x - (this.initialSize / 2),
  438. y: startPoint.y - (this.initialSize / 2),
  439. };
  440. var endPoint = {
  441. x: (this.frame.width / 2) - (this.initialSize / 2),
  442. y: (this.frame.height / 2) - (this.initialSize / 2),
  443. };
  444. return { startPoint: startPoint, endPoint: endPoint };
  445. };
  446. MDCRippleFoundation.prototype.runDeactivationUXLogicIfReady = function () {
  447. var _this = this;
  448. // This method is called both when a pointing device is released, and when
  449. // the activation animation ends. The deactivation animation should only run
  450. // after both of those occur.
  451. var FG_DEACTIVATION = MDCRippleFoundation.cssClasses.FG_DEACTIVATION;
  452. var _a = this.activationState, hasDeactivationUXRun = _a.hasDeactivationUXRun, isActivated = _a.isActivated;
  453. var activationHasEnded = hasDeactivationUXRun || !isActivated;
  454. if (activationHasEnded && this.activationAnimationHasEnded) {
  455. this.rmBoundedActivationClasses();
  456. this.adapter.addClass(FG_DEACTIVATION);
  457. this.fgDeactivationRemovalTimer = setTimeout(function () {
  458. _this.adapter.removeClass(FG_DEACTIVATION);
  459. }, numbers.FG_DEACTIVATION_MS);
  460. }
  461. };
  462. MDCRippleFoundation.prototype.rmBoundedActivationClasses = function () {
  463. var FG_ACTIVATION = MDCRippleFoundation.cssClasses.FG_ACTIVATION;
  464. this.adapter.removeClass(FG_ACTIVATION);
  465. this.activationAnimationHasEnded = false;
  466. this.adapter.computeBoundingRect();
  467. };
  468. MDCRippleFoundation.prototype.resetActivationState = function () {
  469. var _this = this;
  470. this.previousActivationEvent = this.activationState.activationEvent;
  471. this.activationState = this.defaultActivationState();
  472. // Touch devices may fire additional events for the same interaction within
  473. // a short time. Store the previous event until it's safe to assume that
  474. // subsequent events are for new interactions.
  475. setTimeout(function () { return _this.previousActivationEvent = undefined; }, MDCRippleFoundation.numbers.TAP_DELAY_MS);
  476. };
  477. MDCRippleFoundation.prototype.deactivateImpl = function () {
  478. var _this = this;
  479. var activationState = this.activationState;
  480. // This can happen in scenarios such as when you have a keyup event that
  481. // blurs the element.
  482. if (!activationState.isActivated) {
  483. return;
  484. }
  485. var state = __assign({}, activationState);
  486. if (activationState.isProgrammatic) {
  487. requestAnimationFrame(function () {
  488. _this.animateDeactivation(state);
  489. });
  490. this.resetActivationState();
  491. }
  492. else {
  493. this.deregisterDeactivationHandlers();
  494. requestAnimationFrame(function () {
  495. _this.activationState.hasDeactivationUXRun = true;
  496. _this.animateDeactivation(state);
  497. _this.resetActivationState();
  498. });
  499. }
  500. };
  501. MDCRippleFoundation.prototype.animateDeactivation = function (_a) {
  502. var wasActivatedByPointer = _a.wasActivatedByPointer, wasElementMadeActive = _a.wasElementMadeActive;
  503. if (wasActivatedByPointer || wasElementMadeActive) {
  504. this.runDeactivationUXLogicIfReady();
  505. }
  506. };
  507. MDCRippleFoundation.prototype.layoutInternal = function () {
  508. var _this = this;
  509. this.frame = this.adapter.computeBoundingRect();
  510. var maxDim = Math.max(this.frame.height, this.frame.width);
  511. // Surface diameter is treated differently for unbounded vs. bounded
  512. // ripples. Unbounded ripple diameter is calculated smaller since the
  513. // surface is expected to already be padded appropriately to extend the
  514. // hitbox, and the ripple is expected to meet the edges of the padded hitbox
  515. // (which is typically square). Bounded ripples, on the other hand, are
  516. // fully expected to expand beyond the surface's longest diameter
  517. // (calculated based on the diagonal plus a constant padding), and are
  518. // clipped at the surface's border via `overflow: hidden`.
  519. var getBoundedRadius = function () {
  520. var hypotenuse = Math.sqrt(Math.pow(_this.frame.width, 2) + Math.pow(_this.frame.height, 2));
  521. return hypotenuse + MDCRippleFoundation.numbers.PADDING;
  522. };
  523. this.maxRadius = this.adapter.isUnbounded() ? maxDim : getBoundedRadius();
  524. // Ripple is sized as a fraction of the largest dimension of the surface,
  525. // then scales up using a CSS scale transform
  526. var initialSize = Math.floor(maxDim * MDCRippleFoundation.numbers.INITIAL_ORIGIN_SCALE);
  527. // Unbounded ripple size should always be even number to equally center
  528. // align.
  529. if (this.adapter.isUnbounded() && initialSize % 2 !== 0) {
  530. this.initialSize = initialSize - 1;
  531. }
  532. else {
  533. this.initialSize = initialSize;
  534. }
  535. this.fgScale = "" + this.maxRadius / this.initialSize;
  536. this.updateLayoutCssVars();
  537. };
  538. MDCRippleFoundation.prototype.updateLayoutCssVars = function () {
  539. 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;
  540. this.adapter.updateCssVariable(VAR_FG_SIZE, this.initialSize + "px");
  541. this.adapter.updateCssVariable(VAR_FG_SCALE, this.fgScale);
  542. if (this.adapter.isUnbounded()) {
  543. this.unboundedCoords = {
  544. left: Math.round((this.frame.width / 2) - (this.initialSize / 2)),
  545. top: Math.round((this.frame.height / 2) - (this.initialSize / 2)),
  546. };
  547. this.adapter.updateCssVariable(VAR_LEFT, this.unboundedCoords.left + "px");
  548. this.adapter.updateCssVariable(VAR_TOP, this.unboundedCoords.top + "px");
  549. }
  550. };
  551. return MDCRippleFoundation;
  552. }(MDCFoundation));
  553. export { MDCRippleFoundation };
  554. // tslint:disable-next-line:no-default-export Needed for backward compatibility with MDC Web v0.44.0 and earlier.
  555. export default MDCRippleFoundation;
  556. //# sourceMappingURL=foundation.js.map