ripple-loader-Ce3DAhPW.mjs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import { DOCUMENT } from '@angular/common';
  2. import * as i0 from '@angular/core';
  3. import { inject, ANIMATION_MODULE_TYPE, NgZone, Injector, RendererFactory2, Injectable } from '@angular/core';
  4. import { Platform, _bindEventWithOptions, _getEventTarget } from '@angular/cdk/platform';
  5. import { a as MAT_RIPPLE_GLOBAL_OPTIONS, R as RippleRenderer, d as defaultRippleAnimationConfig } from './ripple-BT3tzh6F.mjs';
  6. /** The options for the MatRippleLoader's event listeners. */
  7. const eventListenerOptions = { capture: true };
  8. /**
  9. * The events that should trigger the initialization of the ripple.
  10. * Note that we use `mousedown`, rather than `click`, for mouse devices because
  11. * we can't rely on `mouseenter` in the shadow DOM and `click` happens too late.
  12. */
  13. const rippleInteractionEvents = ['focus', 'mousedown', 'mouseenter', 'touchstart'];
  14. /** The attribute attached to a component whose ripple has not yet been initialized. */
  15. const matRippleUninitialized = 'mat-ripple-loader-uninitialized';
  16. /** Additional classes that should be added to the ripple when it is rendered. */
  17. const matRippleClassName = 'mat-ripple-loader-class-name';
  18. /** Whether the ripple should be centered. */
  19. const matRippleCentered = 'mat-ripple-loader-centered';
  20. /** Whether the ripple should be disabled. */
  21. const matRippleDisabled = 'mat-ripple-loader-disabled';
  22. /**
  23. * Handles attaching ripples on demand.
  24. *
  25. * This service allows us to avoid eagerly creating & attaching MatRipples.
  26. * It works by creating & attaching a ripple only when a component is first interacted with.
  27. *
  28. * @docs-private
  29. */
  30. class MatRippleLoader {
  31. _document = inject(DOCUMENT);
  32. _animationMode = inject(ANIMATION_MODULE_TYPE, { optional: true });
  33. _globalRippleOptions = inject(MAT_RIPPLE_GLOBAL_OPTIONS, { optional: true });
  34. _platform = inject(Platform);
  35. _ngZone = inject(NgZone);
  36. _injector = inject(Injector);
  37. _eventCleanups;
  38. _hosts = new Map();
  39. constructor() {
  40. const renderer = inject(RendererFactory2).createRenderer(null, null);
  41. this._eventCleanups = this._ngZone.runOutsideAngular(() => {
  42. return rippleInteractionEvents.map(name => _bindEventWithOptions(renderer, this._document, name, this._onInteraction, eventListenerOptions));
  43. });
  44. }
  45. ngOnDestroy() {
  46. const hosts = this._hosts.keys();
  47. for (const host of hosts) {
  48. this.destroyRipple(host);
  49. }
  50. this._eventCleanups.forEach(cleanup => cleanup());
  51. }
  52. /**
  53. * Configures the ripple that will be rendered by the ripple loader.
  54. *
  55. * Stores the given information about how the ripple should be configured on the host
  56. * element so that it can later be retrived & used when the ripple is actually created.
  57. */
  58. configureRipple(host, config) {
  59. // Indicates that the ripple has not yet been rendered for this component.
  60. host.setAttribute(matRippleUninitialized, this._globalRippleOptions?.namespace ?? '');
  61. // Store the additional class name(s) that should be added to the ripple element.
  62. if (config.className || !host.hasAttribute(matRippleClassName)) {
  63. host.setAttribute(matRippleClassName, config.className || '');
  64. }
  65. // Store whether the ripple should be centered.
  66. if (config.centered) {
  67. host.setAttribute(matRippleCentered, '');
  68. }
  69. if (config.disabled) {
  70. host.setAttribute(matRippleDisabled, '');
  71. }
  72. }
  73. /** Sets the disabled state on the ripple instance corresponding to the given host element. */
  74. setDisabled(host, disabled) {
  75. const ripple = this._hosts.get(host);
  76. // If the ripple has already been instantiated, just disable it.
  77. if (ripple) {
  78. ripple.target.rippleDisabled = disabled;
  79. if (!disabled && !ripple.hasSetUpEvents) {
  80. ripple.hasSetUpEvents = true;
  81. ripple.renderer.setupTriggerEvents(host);
  82. }
  83. }
  84. else if (disabled) {
  85. // Otherwise, set an attribute so we know what the
  86. // disabled state should be when the ripple is initialized.
  87. host.setAttribute(matRippleDisabled, '');
  88. }
  89. else {
  90. host.removeAttribute(matRippleDisabled);
  91. }
  92. }
  93. /**
  94. * Handles creating and attaching component internals
  95. * when a component is initially interacted with.
  96. */
  97. _onInteraction = (event) => {
  98. const eventTarget = _getEventTarget(event);
  99. if (eventTarget instanceof HTMLElement) {
  100. // TODO(wagnermaciel): Consider batching these events to improve runtime performance.
  101. const element = eventTarget.closest(`[${matRippleUninitialized}="${this._globalRippleOptions?.namespace ?? ''}"]`);
  102. if (element) {
  103. this._createRipple(element);
  104. }
  105. }
  106. };
  107. /** Creates a MatRipple and appends it to the given element. */
  108. _createRipple(host) {
  109. if (!this._document || this._hosts.has(host)) {
  110. return;
  111. }
  112. // Create the ripple element.
  113. host.querySelector('.mat-ripple')?.remove();
  114. const rippleEl = this._document.createElement('span');
  115. rippleEl.classList.add('mat-ripple', host.getAttribute(matRippleClassName));
  116. host.append(rippleEl);
  117. const isNoopAnimations = this._animationMode === 'NoopAnimations';
  118. const globalOptions = this._globalRippleOptions;
  119. const enterDuration = isNoopAnimations
  120. ? 0
  121. : globalOptions?.animation?.enterDuration ?? defaultRippleAnimationConfig.enterDuration;
  122. const exitDuration = isNoopAnimations
  123. ? 0
  124. : globalOptions?.animation?.exitDuration ?? defaultRippleAnimationConfig.exitDuration;
  125. const target = {
  126. rippleDisabled: isNoopAnimations || globalOptions?.disabled || host.hasAttribute(matRippleDisabled),
  127. rippleConfig: {
  128. centered: host.hasAttribute(matRippleCentered),
  129. terminateOnPointerUp: globalOptions?.terminateOnPointerUp,
  130. animation: {
  131. enterDuration,
  132. exitDuration,
  133. },
  134. },
  135. };
  136. const renderer = new RippleRenderer(target, this._ngZone, rippleEl, this._platform, this._injector);
  137. const hasSetUpEvents = !target.rippleDisabled;
  138. if (hasSetUpEvents) {
  139. renderer.setupTriggerEvents(host);
  140. }
  141. this._hosts.set(host, {
  142. target,
  143. renderer,
  144. hasSetUpEvents,
  145. });
  146. host.removeAttribute(matRippleUninitialized);
  147. }
  148. destroyRipple(host) {
  149. const ripple = this._hosts.get(host);
  150. if (ripple) {
  151. ripple.renderer._removeTriggerEvents();
  152. this._hosts.delete(host);
  153. }
  154. }
  155. static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatRippleLoader, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
  156. static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatRippleLoader, providedIn: 'root' });
  157. }
  158. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.6", ngImport: i0, type: MatRippleLoader, decorators: [{
  159. type: Injectable,
  160. args: [{ providedIn: 'root' }]
  161. }], ctorParameters: () => [] });
  162. export { MatRippleLoader as M };
  163. //# sourceMappingURL=ripple-loader-Ce3DAhPW.mjs.map