tooltip.es5.js 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020
  1. /**
  2. * @license
  3. * Copyright Google LLC All Rights Reserved.
  4. *
  5. * Use of this source code is governed by an MIT-style license that can be
  6. * found in the LICENSE file at https://angular.io/license
  7. */
  8. import { animate, keyframes, state, style, transition, trigger } from '@angular/animations';
  9. import { __assign } from 'tslib';
  10. import { AriaDescriber, FocusMonitor, A11yModule } from '@angular/cdk/a11y';
  11. import { Directionality } from '@angular/cdk/bidi';
  12. import { coerceBooleanProperty } from '@angular/cdk/coercion';
  13. import { ESCAPE, hasModifierKey } from '@angular/cdk/keycodes';
  14. import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
  15. import { Overlay, OverlayModule } from '@angular/cdk/overlay';
  16. import { Platform } from '@angular/cdk/platform';
  17. import { ComponentPortal } from '@angular/cdk/portal';
  18. import { ScrollDispatcher } from '@angular/cdk/scrolling';
  19. import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Directive, ElementRef, Inject, InjectionToken, Input, NgZone, Optional, ViewContainerRef, ViewEncapsulation, NgModule } from '@angular/core';
  20. import { HAMMER_LOADER, HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';
  21. import { Subject } from 'rxjs';
  22. import { take, takeUntil } from 'rxjs/operators';
  23. import { CommonModule } from '@angular/common';
  24. import { GestureConfig, MatCommonModule } from '@angular/material/core';
  25. /**
  26. * @fileoverview added by tsickle
  27. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  28. */
  29. /**
  30. * Animations used by MatTooltip.
  31. * \@docs-private
  32. * @type {?}
  33. */
  34. var matTooltipAnimations = {
  35. /**
  36. * Animation that transitions a tooltip in and out.
  37. */
  38. tooltipState: trigger('state', [
  39. state('initial, void, hidden', style({ opacity: 0, transform: 'scale(0)' })),
  40. state('visible', style({ transform: 'scale(1)' })),
  41. transition('* => visible', animate('200ms cubic-bezier(0, 0, 0.2, 1)', keyframes([
  42. style({ opacity: 0, transform: 'scale(0)', offset: 0 }),
  43. style({ opacity: 0.5, transform: 'scale(0.99)', offset: 0.5 }),
  44. style({ opacity: 1, transform: 'scale(1)', offset: 1 })
  45. ]))),
  46. transition('* => hidden', animate('100ms cubic-bezier(0, 0, 0.2, 1)', style({ opacity: 0 }))),
  47. ])
  48. };
  49. /**
  50. * @fileoverview added by tsickle
  51. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  52. */
  53. /**
  54. * Time in ms to throttle repositioning after scroll events.
  55. * @type {?}
  56. */
  57. var SCROLL_THROTTLE_MS = 20;
  58. /**
  59. * CSS class that will be attached to the overlay panel.
  60. * @type {?}
  61. */
  62. var TOOLTIP_PANEL_CLASS = 'mat-tooltip-panel';
  63. /**
  64. * Creates an error to be thrown if the user supplied an invalid tooltip position.
  65. * \@docs-private
  66. * @param {?} position
  67. * @return {?}
  68. */
  69. function getMatTooltipInvalidPositionError(position) {
  70. return Error("Tooltip position \"" + position + "\" is invalid.");
  71. }
  72. /**
  73. * Injection token that determines the scroll handling while a tooltip is visible.
  74. * @type {?}
  75. */
  76. var MAT_TOOLTIP_SCROLL_STRATEGY = new InjectionToken('mat-tooltip-scroll-strategy');
  77. /**
  78. * \@docs-private
  79. * @param {?} overlay
  80. * @return {?}
  81. */
  82. function MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY(overlay) {
  83. return (/**
  84. * @return {?}
  85. */
  86. function () { return overlay.scrollStrategies.reposition({ scrollThrottle: SCROLL_THROTTLE_MS }); });
  87. }
  88. /**
  89. * \@docs-private
  90. * @type {?}
  91. */
  92. var MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY_PROVIDER = {
  93. provide: MAT_TOOLTIP_SCROLL_STRATEGY,
  94. deps: [Overlay],
  95. useFactory: MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY,
  96. };
  97. /**
  98. * Injection token to be used to override the default options for `matTooltip`.
  99. * @type {?}
  100. */
  101. var MAT_TOOLTIP_DEFAULT_OPTIONS = new InjectionToken('mat-tooltip-default-options', {
  102. providedIn: 'root',
  103. factory: MAT_TOOLTIP_DEFAULT_OPTIONS_FACTORY
  104. });
  105. /**
  106. * \@docs-private
  107. * @return {?}
  108. */
  109. function MAT_TOOLTIP_DEFAULT_OPTIONS_FACTORY() {
  110. return {
  111. showDelay: 0,
  112. hideDelay: 0,
  113. touchendHideDelay: 1500,
  114. };
  115. }
  116. /**
  117. * Directive that attaches a material design tooltip to the host element. Animates the showing and
  118. * hiding of a tooltip provided position (defaults to below the element).
  119. *
  120. * https://material.io/design/components/tooltips.html
  121. */
  122. var MatTooltip = /** @class */ (function () {
  123. function MatTooltip(_overlay, _elementRef, _scrollDispatcher, _viewContainerRef, _ngZone, platform, _ariaDescriber, _focusMonitor, scrollStrategy, _dir, _defaultOptions, hammerLoader) {
  124. var _this = this;
  125. this._overlay = _overlay;
  126. this._elementRef = _elementRef;
  127. this._scrollDispatcher = _scrollDispatcher;
  128. this._viewContainerRef = _viewContainerRef;
  129. this._ngZone = _ngZone;
  130. this._ariaDescriber = _ariaDescriber;
  131. this._focusMonitor = _focusMonitor;
  132. this._dir = _dir;
  133. this._defaultOptions = _defaultOptions;
  134. this._position = 'below';
  135. this._disabled = false;
  136. /**
  137. * The default delay in ms before showing the tooltip after show is called
  138. */
  139. this.showDelay = this._defaultOptions.showDelay;
  140. /**
  141. * The default delay in ms before hiding the tooltip after hide is called
  142. */
  143. this.hideDelay = this._defaultOptions.hideDelay;
  144. this._message = '';
  145. this._manualListeners = new Map();
  146. /**
  147. * Emits when the component is destroyed.
  148. */
  149. this._destroyed = new Subject();
  150. this._scrollStrategy = scrollStrategy;
  151. /** @type {?} */
  152. var element = _elementRef.nativeElement;
  153. /** @type {?} */
  154. var hasGestures = typeof window === 'undefined' || ((/** @type {?} */ (window))).Hammer || hammerLoader;
  155. // The mouse events shouldn't be bound on mobile devices, because they can prevent the
  156. // first tap from firing its click event or can cause the tooltip to open for clicks.
  157. if (!platform.IOS && !platform.ANDROID) {
  158. this._manualListeners
  159. .set('mouseenter', (/**
  160. * @return {?}
  161. */
  162. function () { return _this.show(); }))
  163. .set('mouseleave', (/**
  164. * @return {?}
  165. */
  166. function () { return _this.hide(); }));
  167. }
  168. else if (!hasGestures) {
  169. // If Hammerjs isn't loaded, fall back to showing on `touchstart`, otherwise
  170. // there's no way for the user to trigger the tooltip on a touch device.
  171. this._manualListeners.set('touchstart', (/**
  172. * @return {?}
  173. */
  174. function () { return _this.show(); }));
  175. }
  176. this._manualListeners.forEach((/**
  177. * @param {?} listener
  178. * @param {?} event
  179. * @return {?}
  180. */
  181. function (listener, event) { return element.addEventListener(event, listener); }));
  182. _focusMonitor.monitor(_elementRef).pipe(takeUntil(this._destroyed)).subscribe((/**
  183. * @param {?} origin
  184. * @return {?}
  185. */
  186. function (origin) {
  187. // Note that the focus monitor runs outside the Angular zone.
  188. if (!origin) {
  189. _ngZone.run((/**
  190. * @return {?}
  191. */
  192. function () { return _this.hide(0); }));
  193. }
  194. else if (origin === 'keyboard') {
  195. _ngZone.run((/**
  196. * @return {?}
  197. */
  198. function () { return _this.show(); }));
  199. }
  200. }));
  201. if (_defaultOptions && _defaultOptions.position) {
  202. this.position = _defaultOptions.position;
  203. }
  204. }
  205. Object.defineProperty(MatTooltip.prototype, "position", {
  206. /** Allows the user to define the position of the tooltip relative to the parent element */
  207. get: /**
  208. * Allows the user to define the position of the tooltip relative to the parent element
  209. * @return {?}
  210. */
  211. function () { return this._position; },
  212. set: /**
  213. * @param {?} value
  214. * @return {?}
  215. */
  216. function (value) {
  217. if (value !== this._position) {
  218. this._position = value;
  219. if (this._overlayRef) {
  220. this._updatePosition();
  221. if (this._tooltipInstance) {
  222. (/** @type {?} */ (this._tooltipInstance)).show(0);
  223. }
  224. this._overlayRef.updatePosition();
  225. }
  226. }
  227. },
  228. enumerable: true,
  229. configurable: true
  230. });
  231. Object.defineProperty(MatTooltip.prototype, "disabled", {
  232. /** Disables the display of the tooltip. */
  233. get: /**
  234. * Disables the display of the tooltip.
  235. * @return {?}
  236. */
  237. function () { return this._disabled; },
  238. set: /**
  239. * @param {?} value
  240. * @return {?}
  241. */
  242. function (value) {
  243. this._disabled = coerceBooleanProperty(value);
  244. // If tooltip is disabled, hide immediately.
  245. if (this._disabled) {
  246. this.hide(0);
  247. }
  248. },
  249. enumerable: true,
  250. configurable: true
  251. });
  252. Object.defineProperty(MatTooltip.prototype, "message", {
  253. /** The message to be displayed in the tooltip */
  254. get: /**
  255. * The message to be displayed in the tooltip
  256. * @return {?}
  257. */
  258. function () { return this._message; },
  259. set: /**
  260. * @param {?} value
  261. * @return {?}
  262. */
  263. function (value) {
  264. this._ariaDescriber.removeDescription(this._elementRef.nativeElement, this._message);
  265. // If the message is not a string (e.g. number), convert it to a string and trim it.
  266. this._message = value != null ? ("" + value).trim() : '';
  267. if (!this._message && this._isTooltipVisible()) {
  268. this.hide(0);
  269. }
  270. else {
  271. this._updateTooltipMessage();
  272. this._ariaDescriber.describe(this._elementRef.nativeElement, this.message);
  273. }
  274. },
  275. enumerable: true,
  276. configurable: true
  277. });
  278. Object.defineProperty(MatTooltip.prototype, "tooltipClass", {
  279. /** Classes to be passed to the tooltip. Supports the same syntax as `ngClass`. */
  280. get: /**
  281. * Classes to be passed to the tooltip. Supports the same syntax as `ngClass`.
  282. * @return {?}
  283. */
  284. function () { return this._tooltipClass; },
  285. set: /**
  286. * @param {?} value
  287. * @return {?}
  288. */
  289. function (value) {
  290. this._tooltipClass = value;
  291. if (this._tooltipInstance) {
  292. this._setTooltipClass(this._tooltipClass);
  293. }
  294. },
  295. enumerable: true,
  296. configurable: true
  297. });
  298. /**
  299. * Setup styling-specific things
  300. */
  301. /**
  302. * Setup styling-specific things
  303. * @return {?}
  304. */
  305. MatTooltip.prototype.ngOnInit = /**
  306. * Setup styling-specific things
  307. * @return {?}
  308. */
  309. function () {
  310. /** @type {?} */
  311. var element = this._elementRef.nativeElement;
  312. /** @type {?} */
  313. var elementStyle = (/** @type {?} */ (element.style));
  314. if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
  315. // When we bind a gesture event on an element (in this case `longpress`), HammerJS
  316. // will add some inline styles by default, including `user-select: none`. This is
  317. // problematic on iOS and in Safari, because it will prevent users from typing in inputs.
  318. // Since `user-select: none` is not needed for the `longpress` event and can cause unexpected
  319. // behavior for text fields, we always clear the `user-select` to avoid such issues.
  320. elementStyle.webkitUserSelect = elementStyle.userSelect = elementStyle.msUserSelect = '';
  321. }
  322. // Hammer applies `-webkit-user-drag: none` on all elements by default,
  323. // which breaks the native drag&drop. If the consumer explicitly made
  324. // the element draggable, clear the `-webkit-user-drag`.
  325. if (element.draggable && elementStyle.webkitUserDrag === 'none') {
  326. elementStyle.webkitUserDrag = '';
  327. }
  328. };
  329. /**
  330. * Dispose the tooltip when destroyed.
  331. */
  332. /**
  333. * Dispose the tooltip when destroyed.
  334. * @return {?}
  335. */
  336. MatTooltip.prototype.ngOnDestroy = /**
  337. * Dispose the tooltip when destroyed.
  338. * @return {?}
  339. */
  340. function () {
  341. var _this = this;
  342. if (this._overlayRef) {
  343. this._overlayRef.dispose();
  344. this._tooltipInstance = null;
  345. }
  346. // Clean up the event listeners set in the constructor
  347. this._manualListeners.forEach((/**
  348. * @param {?} listener
  349. * @param {?} event
  350. * @return {?}
  351. */
  352. function (listener, event) {
  353. _this._elementRef.nativeElement.removeEventListener(event, listener);
  354. }));
  355. this._manualListeners.clear();
  356. this._destroyed.next();
  357. this._destroyed.complete();
  358. this._ariaDescriber.removeDescription(this._elementRef.nativeElement, this.message);
  359. this._focusMonitor.stopMonitoring(this._elementRef);
  360. };
  361. /** Shows the tooltip after the delay in ms, defaults to tooltip-delay-show or 0ms if no input */
  362. /**
  363. * Shows the tooltip after the delay in ms, defaults to tooltip-delay-show or 0ms if no input
  364. * @param {?=} delay
  365. * @return {?}
  366. */
  367. MatTooltip.prototype.show = /**
  368. * Shows the tooltip after the delay in ms, defaults to tooltip-delay-show or 0ms if no input
  369. * @param {?=} delay
  370. * @return {?}
  371. */
  372. function (delay) {
  373. var _this = this;
  374. if (delay === void 0) { delay = this.showDelay; }
  375. if (this.disabled || !this.message || (this._isTooltipVisible() &&
  376. !(/** @type {?} */ (this._tooltipInstance))._showTimeoutId && !(/** @type {?} */ (this._tooltipInstance))._hideTimeoutId)) {
  377. return;
  378. }
  379. /** @type {?} */
  380. var overlayRef = this._createOverlay();
  381. this._detach();
  382. this._portal = this._portal || new ComponentPortal(TooltipComponent, this._viewContainerRef);
  383. this._tooltipInstance = overlayRef.attach(this._portal).instance;
  384. this._tooltipInstance.afterHidden()
  385. .pipe(takeUntil(this._destroyed))
  386. .subscribe((/**
  387. * @return {?}
  388. */
  389. function () { return _this._detach(); }));
  390. this._setTooltipClass(this._tooltipClass);
  391. this._updateTooltipMessage();
  392. (/** @type {?} */ (this._tooltipInstance)).show(delay);
  393. };
  394. /** Hides the tooltip after the delay in ms, defaults to tooltip-delay-hide or 0ms if no input */
  395. /**
  396. * Hides the tooltip after the delay in ms, defaults to tooltip-delay-hide or 0ms if no input
  397. * @param {?=} delay
  398. * @return {?}
  399. */
  400. MatTooltip.prototype.hide = /**
  401. * Hides the tooltip after the delay in ms, defaults to tooltip-delay-hide or 0ms if no input
  402. * @param {?=} delay
  403. * @return {?}
  404. */
  405. function (delay) {
  406. if (delay === void 0) { delay = this.hideDelay; }
  407. if (this._tooltipInstance) {
  408. this._tooltipInstance.hide(delay);
  409. }
  410. };
  411. /** Shows/hides the tooltip */
  412. /**
  413. * Shows/hides the tooltip
  414. * @return {?}
  415. */
  416. MatTooltip.prototype.toggle = /**
  417. * Shows/hides the tooltip
  418. * @return {?}
  419. */
  420. function () {
  421. this._isTooltipVisible() ? this.hide() : this.show();
  422. };
  423. /** Returns true if the tooltip is currently visible to the user */
  424. /**
  425. * Returns true if the tooltip is currently visible to the user
  426. * @return {?}
  427. */
  428. MatTooltip.prototype._isTooltipVisible = /**
  429. * Returns true if the tooltip is currently visible to the user
  430. * @return {?}
  431. */
  432. function () {
  433. return !!this._tooltipInstance && this._tooltipInstance.isVisible();
  434. };
  435. /** Handles the keydown events on the host element. */
  436. /**
  437. * Handles the keydown events on the host element.
  438. * @param {?} e
  439. * @return {?}
  440. */
  441. MatTooltip.prototype._handleKeydown = /**
  442. * Handles the keydown events on the host element.
  443. * @param {?} e
  444. * @return {?}
  445. */
  446. function (e) {
  447. if (this._isTooltipVisible() && e.keyCode === ESCAPE && !hasModifierKey(e)) {
  448. e.preventDefault();
  449. e.stopPropagation();
  450. this.hide(0);
  451. }
  452. };
  453. /** Handles the touchend events on the host element. */
  454. /**
  455. * Handles the touchend events on the host element.
  456. * @return {?}
  457. */
  458. MatTooltip.prototype._handleTouchend = /**
  459. * Handles the touchend events on the host element.
  460. * @return {?}
  461. */
  462. function () {
  463. this.hide(this._defaultOptions.touchendHideDelay);
  464. };
  465. /** Create the overlay config and position strategy */
  466. /**
  467. * Create the overlay config and position strategy
  468. * @private
  469. * @return {?}
  470. */
  471. MatTooltip.prototype._createOverlay = /**
  472. * Create the overlay config and position strategy
  473. * @private
  474. * @return {?}
  475. */
  476. function () {
  477. var _this = this;
  478. if (this._overlayRef) {
  479. return this._overlayRef;
  480. }
  481. /** @type {?} */
  482. var scrollableAncestors = this._scrollDispatcher.getAncestorScrollContainers(this._elementRef);
  483. // Create connected position strategy that listens for scroll events to reposition.
  484. /** @type {?} */
  485. var strategy = this._overlay.position()
  486. .flexibleConnectedTo(this._elementRef)
  487. .withTransformOriginOn('.mat-tooltip')
  488. .withFlexibleDimensions(false)
  489. .withViewportMargin(8)
  490. .withScrollableContainers(scrollableAncestors);
  491. strategy.positionChanges.pipe(takeUntil(this._destroyed)).subscribe((/**
  492. * @param {?} change
  493. * @return {?}
  494. */
  495. function (change) {
  496. if (_this._tooltipInstance) {
  497. if (change.scrollableViewProperties.isOverlayClipped && _this._tooltipInstance.isVisible()) {
  498. // After position changes occur and the overlay is clipped by
  499. // a parent scrollable then close the tooltip.
  500. _this._ngZone.run((/**
  501. * @return {?}
  502. */
  503. function () { return _this.hide(0); }));
  504. }
  505. }
  506. }));
  507. this._overlayRef = this._overlay.create({
  508. direction: this._dir,
  509. positionStrategy: strategy,
  510. panelClass: TOOLTIP_PANEL_CLASS,
  511. scrollStrategy: this._scrollStrategy()
  512. });
  513. this._updatePosition();
  514. this._overlayRef.detachments()
  515. .pipe(takeUntil(this._destroyed))
  516. .subscribe((/**
  517. * @return {?}
  518. */
  519. function () { return _this._detach(); }));
  520. return this._overlayRef;
  521. };
  522. /** Detaches the currently-attached tooltip. */
  523. /**
  524. * Detaches the currently-attached tooltip.
  525. * @private
  526. * @return {?}
  527. */
  528. MatTooltip.prototype._detach = /**
  529. * Detaches the currently-attached tooltip.
  530. * @private
  531. * @return {?}
  532. */
  533. function () {
  534. if (this._overlayRef && this._overlayRef.hasAttached()) {
  535. this._overlayRef.detach();
  536. }
  537. this._tooltipInstance = null;
  538. };
  539. /** Updates the position of the current tooltip. */
  540. /**
  541. * Updates the position of the current tooltip.
  542. * @private
  543. * @return {?}
  544. */
  545. MatTooltip.prototype._updatePosition = /**
  546. * Updates the position of the current tooltip.
  547. * @private
  548. * @return {?}
  549. */
  550. function () {
  551. /** @type {?} */
  552. var position = (/** @type {?} */ ((/** @type {?} */ (this._overlayRef)).getConfig().positionStrategy));
  553. /** @type {?} */
  554. var origin = this._getOrigin();
  555. /** @type {?} */
  556. var overlay = this._getOverlayPosition();
  557. position.withPositions([
  558. __assign({}, origin.main, overlay.main),
  559. __assign({}, origin.fallback, overlay.fallback)
  560. ]);
  561. };
  562. /**
  563. * Returns the origin position and a fallback position based on the user's position preference.
  564. * The fallback position is the inverse of the origin (e.g. `'below' -> 'above'`).
  565. */
  566. /**
  567. * Returns the origin position and a fallback position based on the user's position preference.
  568. * The fallback position is the inverse of the origin (e.g. `'below' -> 'above'`).
  569. * @return {?}
  570. */
  571. MatTooltip.prototype._getOrigin = /**
  572. * Returns the origin position and a fallback position based on the user's position preference.
  573. * The fallback position is the inverse of the origin (e.g. `'below' -> 'above'`).
  574. * @return {?}
  575. */
  576. function () {
  577. /** @type {?} */
  578. var isLtr = !this._dir || this._dir.value == 'ltr';
  579. /** @type {?} */
  580. var position = this.position;
  581. /** @type {?} */
  582. var originPosition;
  583. if (position == 'above' || position == 'below') {
  584. originPosition = { originX: 'center', originY: position == 'above' ? 'top' : 'bottom' };
  585. }
  586. else if (position == 'before' ||
  587. (position == 'left' && isLtr) ||
  588. (position == 'right' && !isLtr)) {
  589. originPosition = { originX: 'start', originY: 'center' };
  590. }
  591. else if (position == 'after' ||
  592. (position == 'right' && isLtr) ||
  593. (position == 'left' && !isLtr)) {
  594. originPosition = { originX: 'end', originY: 'center' };
  595. }
  596. else {
  597. throw getMatTooltipInvalidPositionError(position);
  598. }
  599. var _a = this._invertPosition(originPosition.originX, originPosition.originY), x = _a.x, y = _a.y;
  600. return {
  601. main: originPosition,
  602. fallback: { originX: x, originY: y }
  603. };
  604. };
  605. /** Returns the overlay position and a fallback position based on the user's preference */
  606. /**
  607. * Returns the overlay position and a fallback position based on the user's preference
  608. * @return {?}
  609. */
  610. MatTooltip.prototype._getOverlayPosition = /**
  611. * Returns the overlay position and a fallback position based on the user's preference
  612. * @return {?}
  613. */
  614. function () {
  615. /** @type {?} */
  616. var isLtr = !this._dir || this._dir.value == 'ltr';
  617. /** @type {?} */
  618. var position = this.position;
  619. /** @type {?} */
  620. var overlayPosition;
  621. if (position == 'above') {
  622. overlayPosition = { overlayX: 'center', overlayY: 'bottom' };
  623. }
  624. else if (position == 'below') {
  625. overlayPosition = { overlayX: 'center', overlayY: 'top' };
  626. }
  627. else if (position == 'before' ||
  628. (position == 'left' && isLtr) ||
  629. (position == 'right' && !isLtr)) {
  630. overlayPosition = { overlayX: 'end', overlayY: 'center' };
  631. }
  632. else if (position == 'after' ||
  633. (position == 'right' && isLtr) ||
  634. (position == 'left' && !isLtr)) {
  635. overlayPosition = { overlayX: 'start', overlayY: 'center' };
  636. }
  637. else {
  638. throw getMatTooltipInvalidPositionError(position);
  639. }
  640. var _a = this._invertPosition(overlayPosition.overlayX, overlayPosition.overlayY), x = _a.x, y = _a.y;
  641. return {
  642. main: overlayPosition,
  643. fallback: { overlayX: x, overlayY: y }
  644. };
  645. };
  646. /** Updates the tooltip message and repositions the overlay according to the new message length */
  647. /**
  648. * Updates the tooltip message and repositions the overlay according to the new message length
  649. * @private
  650. * @return {?}
  651. */
  652. MatTooltip.prototype._updateTooltipMessage = /**
  653. * Updates the tooltip message and repositions the overlay according to the new message length
  654. * @private
  655. * @return {?}
  656. */
  657. function () {
  658. var _this = this;
  659. // Must wait for the message to be painted to the tooltip so that the overlay can properly
  660. // calculate the correct positioning based on the size of the text.
  661. if (this._tooltipInstance) {
  662. this._tooltipInstance.message = this.message;
  663. this._tooltipInstance._markForCheck();
  664. this._ngZone.onMicrotaskEmpty.asObservable().pipe(take(1), takeUntil(this._destroyed)).subscribe((/**
  665. * @return {?}
  666. */
  667. function () {
  668. if (_this._tooltipInstance) {
  669. (/** @type {?} */ (_this._overlayRef)).updatePosition();
  670. }
  671. }));
  672. }
  673. };
  674. /** Updates the tooltip class */
  675. /**
  676. * Updates the tooltip class
  677. * @private
  678. * @param {?} tooltipClass
  679. * @return {?}
  680. */
  681. MatTooltip.prototype._setTooltipClass = /**
  682. * Updates the tooltip class
  683. * @private
  684. * @param {?} tooltipClass
  685. * @return {?}
  686. */
  687. function (tooltipClass) {
  688. if (this._tooltipInstance) {
  689. this._tooltipInstance.tooltipClass = tooltipClass;
  690. this._tooltipInstance._markForCheck();
  691. }
  692. };
  693. /** Inverts an overlay position. */
  694. /**
  695. * Inverts an overlay position.
  696. * @private
  697. * @param {?} x
  698. * @param {?} y
  699. * @return {?}
  700. */
  701. MatTooltip.prototype._invertPosition = /**
  702. * Inverts an overlay position.
  703. * @private
  704. * @param {?} x
  705. * @param {?} y
  706. * @return {?}
  707. */
  708. function (x, y) {
  709. if (this.position === 'above' || this.position === 'below') {
  710. if (y === 'top') {
  711. y = 'bottom';
  712. }
  713. else if (y === 'bottom') {
  714. y = 'top';
  715. }
  716. }
  717. else {
  718. if (x === 'end') {
  719. x = 'start';
  720. }
  721. else if (x === 'start') {
  722. x = 'end';
  723. }
  724. }
  725. return { x: x, y: y };
  726. };
  727. MatTooltip.decorators = [
  728. { type: Directive, args: [{
  729. selector: '[matTooltip]',
  730. exportAs: 'matTooltip',
  731. host: {
  732. '(longpress)': 'show()',
  733. '(keydown)': '_handleKeydown($event)',
  734. '(touchend)': '_handleTouchend()',
  735. },
  736. },] },
  737. ];
  738. /** @nocollapse */
  739. MatTooltip.ctorParameters = function () { return [
  740. { type: Overlay },
  741. { type: ElementRef },
  742. { type: ScrollDispatcher },
  743. { type: ViewContainerRef },
  744. { type: NgZone },
  745. { type: Platform },
  746. { type: AriaDescriber },
  747. { type: FocusMonitor },
  748. { type: undefined, decorators: [{ type: Inject, args: [MAT_TOOLTIP_SCROLL_STRATEGY,] }] },
  749. { type: Directionality, decorators: [{ type: Optional }] },
  750. { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [MAT_TOOLTIP_DEFAULT_OPTIONS,] }] },
  751. { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [HAMMER_LOADER,] }] }
  752. ]; };
  753. MatTooltip.propDecorators = {
  754. position: [{ type: Input, args: ['matTooltipPosition',] }],
  755. disabled: [{ type: Input, args: ['matTooltipDisabled',] }],
  756. showDelay: [{ type: Input, args: ['matTooltipShowDelay',] }],
  757. hideDelay: [{ type: Input, args: ['matTooltipHideDelay',] }],
  758. message: [{ type: Input, args: ['matTooltip',] }],
  759. tooltipClass: [{ type: Input, args: ['matTooltipClass',] }]
  760. };
  761. return MatTooltip;
  762. }());
  763. /**
  764. * Internal component that wraps the tooltip's content.
  765. * \@docs-private
  766. */
  767. var TooltipComponent = /** @class */ (function () {
  768. function TooltipComponent(_changeDetectorRef, _breakpointObserver) {
  769. this._changeDetectorRef = _changeDetectorRef;
  770. this._breakpointObserver = _breakpointObserver;
  771. /**
  772. * Property watched by the animation framework to show or hide the tooltip
  773. */
  774. this._visibility = 'initial';
  775. /**
  776. * Whether interactions on the page should close the tooltip
  777. */
  778. this._closeOnInteraction = false;
  779. /**
  780. * Subject for notifying that the tooltip has been hidden from the view
  781. */
  782. this._onHide = new Subject();
  783. /**
  784. * Stream that emits whether the user has a handset-sized display.
  785. */
  786. this._isHandset = this._breakpointObserver.observe(Breakpoints.Handset);
  787. }
  788. /**
  789. * Shows the tooltip with an animation originating from the provided origin
  790. * @param delay Amount of milliseconds to the delay showing the tooltip.
  791. */
  792. /**
  793. * Shows the tooltip with an animation originating from the provided origin
  794. * @param {?} delay Amount of milliseconds to the delay showing the tooltip.
  795. * @return {?}
  796. */
  797. TooltipComponent.prototype.show = /**
  798. * Shows the tooltip with an animation originating from the provided origin
  799. * @param {?} delay Amount of milliseconds to the delay showing the tooltip.
  800. * @return {?}
  801. */
  802. function (delay) {
  803. var _this = this;
  804. // Cancel the delayed hide if it is scheduled
  805. if (this._hideTimeoutId) {
  806. clearTimeout(this._hideTimeoutId);
  807. this._hideTimeoutId = null;
  808. }
  809. // Body interactions should cancel the tooltip if there is a delay in showing.
  810. this._closeOnInteraction = true;
  811. this._showTimeoutId = setTimeout((/**
  812. * @return {?}
  813. */
  814. function () {
  815. _this._visibility = 'visible';
  816. _this._showTimeoutId = null;
  817. // Mark for check so if any parent component has set the
  818. // ChangeDetectionStrategy to OnPush it will be checked anyways
  819. _this._markForCheck();
  820. }), delay);
  821. };
  822. /**
  823. * Begins the animation to hide the tooltip after the provided delay in ms.
  824. * @param delay Amount of milliseconds to delay showing the tooltip.
  825. */
  826. /**
  827. * Begins the animation to hide the tooltip after the provided delay in ms.
  828. * @param {?} delay Amount of milliseconds to delay showing the tooltip.
  829. * @return {?}
  830. */
  831. TooltipComponent.prototype.hide = /**
  832. * Begins the animation to hide the tooltip after the provided delay in ms.
  833. * @param {?} delay Amount of milliseconds to delay showing the tooltip.
  834. * @return {?}
  835. */
  836. function (delay) {
  837. var _this = this;
  838. // Cancel the delayed show if it is scheduled
  839. if (this._showTimeoutId) {
  840. clearTimeout(this._showTimeoutId);
  841. this._showTimeoutId = null;
  842. }
  843. this._hideTimeoutId = setTimeout((/**
  844. * @return {?}
  845. */
  846. function () {
  847. _this._visibility = 'hidden';
  848. _this._hideTimeoutId = null;
  849. // Mark for check so if any parent component has set the
  850. // ChangeDetectionStrategy to OnPush it will be checked anyways
  851. _this._markForCheck();
  852. }), delay);
  853. };
  854. /** Returns an observable that notifies when the tooltip has been hidden from view. */
  855. /**
  856. * Returns an observable that notifies when the tooltip has been hidden from view.
  857. * @return {?}
  858. */
  859. TooltipComponent.prototype.afterHidden = /**
  860. * Returns an observable that notifies when the tooltip has been hidden from view.
  861. * @return {?}
  862. */
  863. function () {
  864. return this._onHide.asObservable();
  865. };
  866. /** Whether the tooltip is being displayed. */
  867. /**
  868. * Whether the tooltip is being displayed.
  869. * @return {?}
  870. */
  871. TooltipComponent.prototype.isVisible = /**
  872. * Whether the tooltip is being displayed.
  873. * @return {?}
  874. */
  875. function () {
  876. return this._visibility === 'visible';
  877. };
  878. /**
  879. * @return {?}
  880. */
  881. TooltipComponent.prototype.ngOnDestroy = /**
  882. * @return {?}
  883. */
  884. function () {
  885. this._onHide.complete();
  886. };
  887. /**
  888. * @return {?}
  889. */
  890. TooltipComponent.prototype._animationStart = /**
  891. * @return {?}
  892. */
  893. function () {
  894. this._closeOnInteraction = false;
  895. };
  896. /**
  897. * @param {?} event
  898. * @return {?}
  899. */
  900. TooltipComponent.prototype._animationDone = /**
  901. * @param {?} event
  902. * @return {?}
  903. */
  904. function (event) {
  905. /** @type {?} */
  906. var toState = (/** @type {?} */ (event.toState));
  907. if (toState === 'hidden' && !this.isVisible()) {
  908. this._onHide.next();
  909. }
  910. if (toState === 'visible' || toState === 'hidden') {
  911. this._closeOnInteraction = true;
  912. }
  913. };
  914. /**
  915. * Interactions on the HTML body should close the tooltip immediately as defined in the
  916. * material design spec.
  917. * https://material.io/design/components/tooltips.html#behavior
  918. */
  919. /**
  920. * Interactions on the HTML body should close the tooltip immediately as defined in the
  921. * material design spec.
  922. * https://material.io/design/components/tooltips.html#behavior
  923. * @return {?}
  924. */
  925. TooltipComponent.prototype._handleBodyInteraction = /**
  926. * Interactions on the HTML body should close the tooltip immediately as defined in the
  927. * material design spec.
  928. * https://material.io/design/components/tooltips.html#behavior
  929. * @return {?}
  930. */
  931. function () {
  932. if (this._closeOnInteraction) {
  933. this.hide(0);
  934. }
  935. };
  936. /**
  937. * Marks that the tooltip needs to be checked in the next change detection run.
  938. * Mainly used for rendering the initial text before positioning a tooltip, which
  939. * can be problematic in components with OnPush change detection.
  940. */
  941. /**
  942. * Marks that the tooltip needs to be checked in the next change detection run.
  943. * Mainly used for rendering the initial text before positioning a tooltip, which
  944. * can be problematic in components with OnPush change detection.
  945. * @return {?}
  946. */
  947. TooltipComponent.prototype._markForCheck = /**
  948. * Marks that the tooltip needs to be checked in the next change detection run.
  949. * Mainly used for rendering the initial text before positioning a tooltip, which
  950. * can be problematic in components with OnPush change detection.
  951. * @return {?}
  952. */
  953. function () {
  954. this._changeDetectorRef.markForCheck();
  955. };
  956. TooltipComponent.decorators = [
  957. { type: Component, args: [{selector: 'mat-tooltip-component',
  958. template: "<div class=\"mat-tooltip\" [ngClass]=\"tooltipClass\" [class.mat-tooltip-handset]=\"(_isHandset | async)?.matches\" [@state]=\"_visibility\" (@state.start)=\"_animationStart()\" (@state.done)=\"_animationDone($event)\">{{message}}</div>",
  959. styles: [".mat-tooltip-panel{pointer-events:none!important}.mat-tooltip{color:#fff;border-radius:4px;margin:14px;max-width:250px;padding-left:8px;padding-right:8px;overflow:hidden;text-overflow:ellipsis}@media (-ms-high-contrast:active){.mat-tooltip{outline:solid 1px}}.mat-tooltip-handset{margin:24px;padding-left:16px;padding-right:16px}"],
  960. encapsulation: ViewEncapsulation.None,
  961. changeDetection: ChangeDetectionStrategy.OnPush,
  962. animations: [matTooltipAnimations.tooltipState],
  963. host: {
  964. // Forces the element to have a layout in IE and Edge. This fixes issues where the element
  965. // won't be rendered if the animations are disabled or there is no web animations polyfill.
  966. '[style.zoom]': '_visibility === "visible" ? 1 : null',
  967. '(body:click)': 'this._handleBodyInteraction()',
  968. 'aria-hidden': 'true',
  969. }
  970. },] },
  971. ];
  972. /** @nocollapse */
  973. TooltipComponent.ctorParameters = function () { return [
  974. { type: ChangeDetectorRef },
  975. { type: BreakpointObserver }
  976. ]; };
  977. return TooltipComponent;
  978. }());
  979. /**
  980. * @fileoverview added by tsickle
  981. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  982. */
  983. var MatTooltipModule = /** @class */ (function () {
  984. function MatTooltipModule() {
  985. }
  986. MatTooltipModule.decorators = [
  987. { type: NgModule, args: [{
  988. imports: [
  989. A11yModule,
  990. CommonModule,
  991. OverlayModule,
  992. MatCommonModule,
  993. ],
  994. exports: [MatTooltip, TooltipComponent, MatCommonModule],
  995. declarations: [MatTooltip, TooltipComponent],
  996. entryComponents: [TooltipComponent],
  997. providers: [
  998. MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY_PROVIDER,
  999. { provide: HAMMER_GESTURE_CONFIG, useClass: GestureConfig },
  1000. ]
  1001. },] },
  1002. ];
  1003. return MatTooltipModule;
  1004. }());
  1005. /**
  1006. * @fileoverview added by tsickle
  1007. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  1008. */
  1009. /**
  1010. * @fileoverview added by tsickle
  1011. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  1012. */
  1013. export { MatTooltipModule, getMatTooltipInvalidPositionError, MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY, MAT_TOOLTIP_DEFAULT_OPTIONS_FACTORY, SCROLL_THROTTLE_MS, TOOLTIP_PANEL_CLASS, MAT_TOOLTIP_SCROLL_STRATEGY, MAT_TOOLTIP_SCROLL_STRATEGY_FACTORY_PROVIDER, MAT_TOOLTIP_DEFAULT_OPTIONS, MatTooltip, TooltipComponent, matTooltipAnimations };
  1014. //# sourceMappingURL=tooltip.es5.js.map