triggers.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /**
  2. * @fileoverview added by tsickle
  3. * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  4. */
  5. import { Observable, merge } from 'rxjs';
  6. import { share, filter, delay, map } from 'rxjs/operators';
  7. export class Trigger {
  8. /**
  9. * @param {?} open
  10. * @param {?=} close
  11. */
  12. constructor(open, close) {
  13. this.open = open;
  14. this.close = close;
  15. if (!close) {
  16. this.close = open;
  17. }
  18. }
  19. /**
  20. * @return {?}
  21. */
  22. isManual() { return this.open === 'manual' || this.close === 'manual'; }
  23. }
  24. if (false) {
  25. /** @type {?} */
  26. Trigger.prototype.open;
  27. /** @type {?} */
  28. Trigger.prototype.close;
  29. }
  30. /** @type {?} */
  31. const DEFAULT_ALIASES = {
  32. 'hover': ['mouseenter', 'mouseleave'],
  33. 'focus': ['focusin', 'focusout'],
  34. };
  35. /**
  36. * @param {?} triggers
  37. * @param {?=} aliases
  38. * @return {?}
  39. */
  40. export function parseTriggers(triggers, aliases = DEFAULT_ALIASES) {
  41. /** @type {?} */
  42. const trimmedTriggers = (triggers || '').trim();
  43. if (trimmedTriggers.length === 0) {
  44. return [];
  45. }
  46. /** @type {?} */
  47. const parsedTriggers = trimmedTriggers.split(/\s+/).map((/**
  48. * @param {?} trigger
  49. * @return {?}
  50. */
  51. trigger => trigger.split(':'))).map((/**
  52. * @param {?} triggerPair
  53. * @return {?}
  54. */
  55. (triggerPair) => {
  56. /** @type {?} */
  57. let alias = aliases[triggerPair[0]] || triggerPair;
  58. return new Trigger(alias[0], alias[1]);
  59. }));
  60. /** @type {?} */
  61. const manualTriggers = parsedTriggers.filter((/**
  62. * @param {?} triggerPair
  63. * @return {?}
  64. */
  65. triggerPair => triggerPair.isManual()));
  66. if (manualTriggers.length > 1) {
  67. throw 'Triggers parse error: only one manual trigger is allowed';
  68. }
  69. if (manualTriggers.length === 1 && parsedTriggers.length > 1) {
  70. throw 'Triggers parse error: manual trigger can\'t be mixed with other triggers';
  71. }
  72. return parsedTriggers;
  73. }
  74. /**
  75. * @param {?} renderer
  76. * @param {?} nativeElement
  77. * @param {?} triggers
  78. * @param {?} isOpenedFn
  79. * @return {?}
  80. */
  81. export function observeTriggers(renderer, nativeElement, triggers, isOpenedFn) {
  82. return new Observable((/**
  83. * @param {?} subscriber
  84. * @return {?}
  85. */
  86. subscriber => {
  87. /** @type {?} */
  88. const listeners = [];
  89. /** @type {?} */
  90. const openFn = (/**
  91. * @return {?}
  92. */
  93. () => subscriber.next(true));
  94. /** @type {?} */
  95. const closeFn = (/**
  96. * @return {?}
  97. */
  98. () => subscriber.next(false));
  99. /** @type {?} */
  100. const toggleFn = (/**
  101. * @return {?}
  102. */
  103. () => subscriber.next(!isOpenedFn()));
  104. triggers.forEach((/**
  105. * @param {?} trigger
  106. * @return {?}
  107. */
  108. (trigger) => {
  109. if (trigger.open === trigger.close) {
  110. listeners.push(renderer.listen(nativeElement, trigger.open, toggleFn));
  111. }
  112. else {
  113. listeners.push(renderer.listen(nativeElement, trigger.open, openFn), renderer.listen(nativeElement, trigger.close, closeFn));
  114. }
  115. }));
  116. return (/**
  117. * @return {?}
  118. */
  119. () => { listeners.forEach((/**
  120. * @param {?} unsubscribeFn
  121. * @return {?}
  122. */
  123. unsubscribeFn => unsubscribeFn())); });
  124. }));
  125. }
  126. /** @type {?} */
  127. const delayOrNoop = (/**
  128. * @template T
  129. * @param {?} time
  130. * @return {?}
  131. */
  132. (time) => time > 0 ? delay(time) : (/**
  133. * @param {?} a
  134. * @return {?}
  135. */
  136. (a) => a));
  137. const ɵ0 = delayOrNoop;
  138. /**
  139. * @param {?} openDelay
  140. * @param {?} closeDelay
  141. * @param {?} isOpenedFn
  142. * @return {?}
  143. */
  144. export function triggerDelay(openDelay, closeDelay, isOpenedFn) {
  145. return (/**
  146. * @param {?} input$
  147. * @return {?}
  148. */
  149. (input$) => {
  150. /** @type {?} */
  151. let pending = null;
  152. /** @type {?} */
  153. const filteredInput$ = input$.pipe(map((/**
  154. * @param {?} open
  155. * @return {?}
  156. */
  157. open => ({ open }))), filter((/**
  158. * @param {?} event
  159. * @return {?}
  160. */
  161. event => {
  162. /** @type {?} */
  163. const currentlyOpen = isOpenedFn();
  164. if (currentlyOpen !== event.open && (!pending || pending.open === currentlyOpen)) {
  165. pending = event;
  166. return true;
  167. }
  168. if (pending && pending.open !== event.open) {
  169. pending = null;
  170. }
  171. return false;
  172. })), share());
  173. /** @type {?} */
  174. const delayedOpen$ = filteredInput$.pipe(filter((/**
  175. * @param {?} event
  176. * @return {?}
  177. */
  178. event => event.open)), delayOrNoop(openDelay));
  179. /** @type {?} */
  180. const delayedClose$ = filteredInput$.pipe(filter((/**
  181. * @param {?} event
  182. * @return {?}
  183. */
  184. event => !event.open)), delayOrNoop(closeDelay));
  185. return merge(delayedOpen$, delayedClose$)
  186. .pipe(filter((/**
  187. * @param {?} event
  188. * @return {?}
  189. */
  190. event => {
  191. if (event === pending) {
  192. pending = null;
  193. return event.open !== isOpenedFn();
  194. }
  195. return false;
  196. })), map((/**
  197. * @param {?} event
  198. * @return {?}
  199. */
  200. event => event.open)));
  201. });
  202. }
  203. /**
  204. * @param {?} renderer
  205. * @param {?} nativeElement
  206. * @param {?} triggers
  207. * @param {?} isOpenedFn
  208. * @param {?} openFn
  209. * @param {?} closeFn
  210. * @param {?=} openDelay
  211. * @param {?=} closeDelay
  212. * @return {?}
  213. */
  214. export function listenToTriggers(renderer, nativeElement, triggers, isOpenedFn, openFn, closeFn, openDelay = 0, closeDelay = 0) {
  215. /** @type {?} */
  216. const parsedTriggers = parseTriggers(triggers);
  217. if (parsedTriggers.length === 1 && parsedTriggers[0].isManual()) {
  218. return (/**
  219. * @return {?}
  220. */
  221. () => { });
  222. }
  223. /** @type {?} */
  224. const subscription = observeTriggers(renderer, nativeElement, parsedTriggers, isOpenedFn)
  225. .pipe(triggerDelay(openDelay, closeDelay, isOpenedFn))
  226. .subscribe((/**
  227. * @param {?} open
  228. * @return {?}
  229. */
  230. open => (open ? openFn() : closeFn())));
  231. return (/**
  232. * @return {?}
  233. */
  234. () => subscription.unsubscribe());
  235. }
  236. export { ɵ0 };
  237. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJpZ2dlcnMuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AbmctYm9vdHN0cmFwL25nLWJvb3RzdHJhcC8iLCJzb3VyY2VzIjpbInV0aWwvdHJpZ2dlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBQyxVQUFVLEVBQUUsS0FBSyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQ3ZDLE9BQU8sRUFBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUV6RCxNQUFNLE9BQU8sT0FBTzs7Ozs7SUFDbEIsWUFBbUIsSUFBWSxFQUFTLEtBQWM7UUFBbkMsU0FBSSxHQUFKLElBQUksQ0FBUTtRQUFTLFVBQUssR0FBTCxLQUFLLENBQVM7UUFDcEQsSUFBSSxDQUFDLEtBQUssRUFBRTtZQUNWLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1NBQ25CO0lBQ0gsQ0FBQzs7OztJQUVELFFBQVEsS0FBSyxPQUFPLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUSxJQUFJLElBQUksQ0FBQyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQztDQUN6RTs7O0lBUGEsdUJBQW1COztJQUFFLHdCQUFxQjs7O01BU2xELGVBQWUsR0FBRztJQUN0QixPQUFPLEVBQUUsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDO0lBQ3JDLE9BQU8sRUFBRSxDQUFDLFNBQVMsRUFBRSxVQUFVLENBQUM7Q0FDakM7Ozs7OztBQUVELE1BQU0sVUFBVSxhQUFhLENBQUMsUUFBZ0IsRUFBRSxPQUFPLEdBQUcsZUFBZTs7VUFDakUsZUFBZSxHQUFHLENBQUMsUUFBUSxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksRUFBRTtJQUUvQyxJQUFJLGVBQWUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ2hDLE9BQU8sRUFBRSxDQUFDO0tBQ1g7O1VBRUssY0FBYyxHQUFHLGVBQWUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFD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QUMsQ0FBQyxDQUFDO0lBQ3BDLENBQUMsRUFBQztBQUNKLENBQUM7Ozs7Ozs7Ozs7OztBQUVELE1BQU0sVUFBVSxnQkFBZ0IsQ0FDNUIsUUFBYSxFQUFFLGFBQWtCLEVBQUUsUUFBZ0IsRUFBRSxVQUF5QixFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsU0FBUyxHQUFHLENBQUMsRUFDOUcsVUFBVSxHQUFHLENBQUM7O1VBQ1YsY0FBYyxHQUFHLGFBQWEsQ0FBQyxRQUFRLENBQUM7SUFFOUMsSUFBSSxjQUFjLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7UUFDL0Q7OztRQUFPLEdBQUcsRUFBRSxHQUFFLENBQUMsRUFBQztLQUNqQjs7VUFFSyxZQUFZLEdBQUcsZUFBZSxDQUFDLFFBQVEsRUFBRSxhQUFhLEVBQUUsY0FBYyxFQUFFLFVBQVUsQ0FBQztTQUMvRCxJQUFJLENBQUMsWUFBWSxDQUFDLFNBQVMsRUFBRSxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7U0FDckQsU0FBUzs7OztJQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxFQUFDO0lBRTFFOzs7SUFBTyxHQUFHLEVBQUUsQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLEVBQUM7QUFDMUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7T2JzZXJ2YWJsZSwgbWVyZ2V9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtzaGFyZSwgZmlsdGVyLCBkZWxheSwgbWFwfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmV4cG9ydCBjbGFzcyBUcmlnZ2VyIHtcbiAgY29uc3RydWN0b3IocHVibGljIG9wZW46IHN0cmluZywgcHVibGljIGNsb3NlPzogc3RyaW5nKSB7XG4gICAgaWYgKCFjbG9zZSkge1xuICAgICAgdGhpcy5jbG9zZSA9IG9wZW47XG4gICAgfVxuICB9XG5cbiAgaXNNYW51YWwoKSB7IHJldHVybiB0aGlzLm9wZW4gPT09ICdtYW51YWwnIHx8IHRoaXMuY2xvc2UgPT09ICdtYW51YWwnOyB9XG59XG5cbmNvbnN0IERFRkFVTFRfQUxJQVNFUyA9IHtcbiAgJ2hvdmVyJzogWydtb3VzZWVudGVyJywgJ21vdXNlbGVhdmUnXSxcbiAgJ2ZvY3VzJzogWydmb2N1c2luJywgJ2ZvY3Vzb3V0J10sXG59O1xuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VUcmlnZ2Vycyh0cmlnZ2Vyczogc3RyaW5nLCBhbGlhc2VzID0gREVGQVVMVF9BTElBU0VTKTogVHJpZ2dlcltdIHtcbiAgY29uc3QgdHJpbW1lZFRyaWdnZXJzID0gKHRyaWdnZXJzIHx8ICcnKS50cmltKCk7XG5cbiAgaWYgKHRyaW1tZWRUcmlnZ2Vycy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICBjb25zdCBwYXJzZWRUcmlnZ2VycyA9IHRyaW1tZWRUcmlnZ2Vycy5zcGxpdCgvXFxzKy8pLm1hcCh0cmlnZ2VyID0+IHRyaWdnZXIuc3BsaXQoJzonKSkubWFwKCh0cmlnZ2VyUGFpcikgPT4ge1xuICAgIGxldCBhbGlhcyA9IGFsaWFzZXNbdHJpZ2dlclBhaXJbMF1dIHx8IHRyaWdnZXJQYWlyO1xuICAgIHJldHVybiBuZXcgVHJpZ2dlcihhbGlhc1swXSwgYWxpYXNbMV0pO1xuICB9KTtcblxuICBjb25zdCBtYW51YWxUcmlnZ2VycyA9IHBhcnNlZFRyaWdnZXJzLmZpbHRlcih0cmlnZ2VyUGFpciA9PiB0cmlnZ2VyUGFpci5pc01hbnVhbCgpKTtcblxuICBpZiAobWFudWFsVHJpZ2dlcnMubGVuZ3RoID4gMSkge1xuICAgIHRocm93ICdUcmlnZ2VycyBwYXJzZSBlcnJvcjogb25seSBvbmUgbWFudWFsIHRyaWdnZXIgaXMgYWxsb3dlZCc7XG4gIH1cblxuICBpZiAobWFudWFsVHJpZ2dlcnMubGVuZ3RoID09PSAxICYmIHBhcnNlZFRyaWdnZXJzLmxlbmd0aCA+IDEpIHtcbiAgICB0aHJvdyAnVHJpZ2dlcnMgcGFyc2UgZXJyb3I6IG1hbnVhbCB0cmlnZ2VyIGNhblxcJ3QgYmUgbWl4ZWQgd2l0aCBvdGhlciB0cmlnZ2Vycyc7XG4gIH1cblxuICByZXR1cm4gcGFyc2VkVHJpZ2dlcnM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvYnNlcnZlVHJpZ2dlcnMocmVuZGVyZXI6IGFueSwgbmF0aXZlRWxlbWVudDogYW55LCB0cmlnZ2VyczogVHJpZ2dlcltdLCBpc09wZW5lZEZuOiAoKSA9PiBib29sZWFuKSB7XG4gIHJldHVybiBuZXcgT2JzZXJ2YWJsZTxib29sZWFuPihzdWJzY3JpYmVyID0+IHtcbiAgICBjb25zdCBsaXN0ZW5lcnMgPSBbXTtcbiAgICBjb25zdCBvcGVuRm4gPSAoKSA9PiBzdWJzY3JpYmVyLm5leHQodHJ1ZSk7XG4gICAgY29uc3QgY2xvc2VGbiA9ICgpID0+IHN1YnNjcmliZXIubmV4dChmYWxzZSk7XG4gICAgY29uc3QgdG9nZ2xlRm4gPSAoKSA9PiBzdWJzY3JpYmVyLm5leHQoIWlzT3BlbmVkRm4oKSk7XG5cbiAgICB0cmlnZ2Vycy5mb3JFYWNoKCh0cmlnZ2VyOiBUcmlnZ2VyKSA9PiB7XG4gICAgICBpZiAodHJpZ2dlci5vcGVuID09PSB0cmlnZ2VyLmNsb3NlKSB7XG4gICAgICAgIGxpc3RlbmVycy5wdXNoKHJlbmRlcmVyLmxpc3RlbihuYXRpdmVFbGVtZW50LCB0cmlnZ2VyLm9wZW4sIHRvZ2dsZUZuKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsaXN0ZW5lcnMucHVzaChcbiAgICAgICAgICAgIHJlbmRlcmVyLmxpc3RlbihuYXRpdmVFbGVtZW50LCB0cmlnZ2VyLm9wZW4sIG9wZW5GbiksXG4gICAgICAgICAgICByZW5kZXJlci5saXN0ZW4obmF0aXZlRWxlbWVudCwgdHJpZ2dlci5jbG9zZSwgY2xvc2VGbikpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuICgpID0+IHsgbGlzdGVuZXJzLmZvckVhY2godW5zdWJzY3JpYmVGbiA9PiB1bnN1YnNjcmliZUZuKCkpOyB9O1xuICB9KTtcbn1cblxuY29uc3QgZGVsYXlPck5vb3AgPSA8VD4odGltZTogbnVtYmVyKSA9PiB0aW1lID4gMCA/IGRlbGF5PFQ+KHRpbWUpIDogKGE6IE9ic2VydmFibGU8VD4pID0+IGE7XG5cbmV4cG9ydCBmdW5jdGlvbiB0cmlnZ2VyRGVsYXkob3BlbkRlbGF5OiBudW1iZXIsIGNsb3NlRGVsYXk6IG51bWJlciwgaXNPcGVuZWRGbjogKCkgPT4gYm9vbGVhbikge1xuICByZXR1cm4gKGlucHV0JDogT2JzZXJ2YWJsZTxib29sZWFuPikgPT4ge1xuICAgIGxldCBwZW5kaW5nID0gbnVsbDtcbiAgICBjb25zdCBmaWx0ZXJlZElucHV0JCA9IGlucHV0JC5waXBlKFxuICAgICAgICBtYXAob3BlbiA9PiAoe29wZW59KSksIGZpbHRlcihldmVudCA9PiB7XG4gICAgICAgICAgY29uc3QgY3VycmVudGx5T3BlbiA9IGlzT3BlbmVkRm4oKTtcbiAgICAgICAgICBpZiAoY3VycmVudGx5T3BlbiAhPT0gZXZlbnQub3BlbiAmJiAoIXBlbmRpbmcgfHwgcGVuZGluZy5vcGVuID09PSBjdXJyZW50bHlPcGVuKSkge1xuICAgICAgICAgICAgcGVuZGluZyA9IGV2ZW50O1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChwZW5kaW5nICYmIHBlbmRpbmcub3BlbiAhPT0gZXZlbnQub3Blbikge1xuICAgICAgICAgICAgcGVuZGluZyA9IG51bGw7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSksXG4gICAgICAgIHNoYXJlKCkpO1xuICAgIGNvbnN0IGRlbGF5ZWRPcGVuJCA9IGZpbHRlcmVkSW5wdXQkLnBpcGUoZmlsdGVyKGV2ZW50ID0+IGV2ZW50Lm9wZW4pLCBkZWxheU9yTm9vcChvcGVuRGVsYXkpKTtcbiAgICBjb25zdCBkZWxheWVkQ2xvc2UkID0gZmlsdGVyZWRJbnB1dCQucGlwZShmaWx0ZXIoZXZlbnQgPT4gIWV2ZW50Lm9wZW4pLCBkZWxheU9yTm9vcChjbG9zZURlbGF5KSk7XG4gICAgcmV0dXJuIG1lcmdlKGRlbGF5ZWRPcGVuJCwgZGVsYXllZENsb3NlJClcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICBmaWx0ZXIoZXZlbnQgPT4ge1xuICAgICAgICAgICAgICBpZiAoZXZlbnQgPT09IHBlbmRpbmcpIHtcbiAgICAgICAgICAgICAgICBwZW5kaW5nID0gbnVsbDtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXZlbnQub3BlbiAhPT0gaXNPcGVuZWRGbigpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgbWFwKGV2ZW50ID0+IGV2ZW50Lm9wZW4pKTtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGxpc3RlblRvVHJpZ2dlcnMoXG4gICAgcmVuZGVyZXI6IGFueSwgbmF0aXZlRWxlbWVudDogYW55LCB0cmlnZ2Vyczogc3RyaW5nLCBpc09wZW5lZEZuOiAoKSA9PiBib29sZWFuLCBvcGVuRm4sIGNsb3NlRm4sIG9wZW5EZWxheSA9IDAsXG4gICAgY2xvc2VEZWxheSA9IDApIHtcbiAgY29uc3QgcGFyc2VkVHJpZ2dlcnMgPSBwYXJzZVRyaWdnZXJzKHRyaWdnZXJzKTtcblxuICBpZiAocGFyc2VkVHJpZ2dlcnMubGVuZ3RoID09PSAxICYmIHBhcnNlZFRyaWdnZXJzWzBdLmlzTWFudWFsKCkpIHtcbiAgICByZXR1cm4gKCkgPT4ge307XG4gIH1cblxuICBjb25zdCBzdWJzY3JpcHRpb24gPSBvYnNlcnZlVHJpZ2dlcnMocmVuZGVyZXIsIG5hdGl2ZUVsZW1lbnQsIHBhcnNlZFRyaWdnZXJzLCBpc09wZW5lZEZuKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgLnBpcGUodHJpZ2dlckRlbGF5KG9wZW5EZWxheSwgY2xvc2VEZWxheSwgaXNPcGVuZWRGbikpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKG9wZW4gPT4gKG9wZW4gPyBvcGVuRm4oKSA6IGNsb3NlRm4oKSkpO1xuXG4gIHJldHVybiAoKSA9PiBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbn1cbiJdfQ==