@spartan-ng/brain 0.0.1-alpha.422 → 0.0.1-alpha.424
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/spartan-ng-brain-accordion.mjs +16 -16
- package/fesm2022/spartan-ng-brain-alert-dialog.mjs +22 -22
- package/fesm2022/spartan-ng-brain-avatar.mjs +16 -16
- package/fesm2022/spartan-ng-brain-calendar.mjs +31 -31
- package/fesm2022/spartan-ng-brain-checkbox.mjs +7 -8
- package/fesm2022/spartan-ng-brain-checkbox.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-collapsible.mjs +13 -13
- package/fesm2022/spartan-ng-brain-command.mjs +22 -22
- package/fesm2022/spartan-ng-brain-dialog.mjs +28 -28
- package/fesm2022/spartan-ng-brain-form-field.mjs +3 -3
- package/fesm2022/spartan-ng-brain-form-field.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-forms.mjs +6 -6
- package/fesm2022/spartan-ng-brain-hover-card.mjs +16 -16
- package/fesm2022/spartan-ng-brain-label.mjs +7 -7
- package/fesm2022/spartan-ng-brain-menu.mjs +40 -40
- package/fesm2022/spartan-ng-brain-popover.mjs +16 -16
- package/fesm2022/spartan-ng-brain-progress.mjs +10 -10
- package/fesm2022/spartan-ng-brain-radio-group.mjs +10 -10
- package/fesm2022/spartan-ng-brain-select.mjs +37 -38
- package/fesm2022/spartan-ng-brain-select.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-separator.mjs +7 -7
- package/fesm2022/spartan-ng-brain-sheet.mjs +25 -25
- package/fesm2022/spartan-ng-brain-slider.mjs +22 -20
- package/fesm2022/spartan-ng-brain-slider.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-switch.mjs +10 -12
- package/fesm2022/spartan-ng-brain-switch.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-table.mjs +22 -24
- package/fesm2022/spartan-ng-brain-table.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-tabs.mjs +19 -19
- package/fesm2022/spartan-ng-brain-tabs.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-toggle.mjs +14 -14
- package/fesm2022/spartan-ng-brain-tooltip.mjs +16 -17
- package/fesm2022/spartan-ng-brain-tooltip.mjs.map +1 -1
- package/form-field/lib/brn-form-field-control.d.ts +1 -1
- package/package.json +5 -63
- package/slider/lib/brn-slider-track.directive.d.ts +1 -0
- package/tabs/lib/brn-tabs-paginated-list.directive.d.ts +1 -1
- package/esm2022/accordion/index.mjs +0 -31
- package/esm2022/accordion/lib/brn-accordion-content.component.mjs +0 -50
- package/esm2022/accordion/lib/brn-accordion.directive.mjs +0 -185
- package/esm2022/accordion/spartan-ng-brain-accordion.mjs +0 -5
- package/esm2022/alert-dialog/index.mjs +0 -45
- package/esm2022/alert-dialog/lib/brn-alert-dialog-content.directive.mjs +0 -17
- package/esm2022/alert-dialog/lib/brn-alert-dialog-description.directive.mjs +0 -18
- package/esm2022/alert-dialog/lib/brn-alert-dialog-overlay.component.mjs +0 -20
- package/esm2022/alert-dialog/lib/brn-alert-dialog-title.directive.mjs +0 -18
- package/esm2022/alert-dialog/lib/brn-alert-dialog-trigger.directive.mjs +0 -34
- package/esm2022/alert-dialog/lib/brn-alert-dialog.component.mjs +0 -41
- package/esm2022/alert-dialog/spartan-ng-brain-alert-dialog.mjs +0 -5
- package/esm2022/avatar/index.mjs +0 -23
- package/esm2022/avatar/lib/brn-avatar.component.mjs +0 -31
- package/esm2022/avatar/lib/fallback/brn-avatar-fallback.directive.mjs +0 -21
- package/esm2022/avatar/lib/fallback/index.mjs +0 -2
- package/esm2022/avatar/lib/image/brn-avatar-image.directive.mjs +0 -29
- package/esm2022/avatar/lib/image/index.mjs +0 -2
- package/esm2022/avatar/lib/util/hex-color-for.mjs +0 -22
- package/esm2022/avatar/lib/util/index.mjs +0 -4
- package/esm2022/avatar/lib/util/initials.pipe.mjs +0 -27
- package/esm2022/avatar/lib/util/is-bright.mjs +0 -12
- package/esm2022/avatar/spartan-ng-brain-avatar.mjs +0 -5
- package/esm2022/calendar/index.mjs +0 -62
- package/esm2022/calendar/lib/brn-calendar-cell-button.directive.mjs +0 -160
- package/esm2022/calendar/lib/brn-calendar-cell.directive.mjs +0 -17
- package/esm2022/calendar/lib/brn-calendar-grid.directive.mjs +0 -21
- package/esm2022/calendar/lib/brn-calendar-header.directive.mjs +0 -22
- package/esm2022/calendar/lib/brn-calendar-next-button.directive.mjs +0 -42
- package/esm2022/calendar/lib/brn-calendar-previous-button.directive.mjs +0 -42
- package/esm2022/calendar/lib/brn-calendar-week.directive.mjs +0 -67
- package/esm2022/calendar/lib/brn-calendar-weekday.directive.mjs +0 -48
- package/esm2022/calendar/lib/brn-calendar.directive.mjs +0 -154
- package/esm2022/calendar/lib/brn-calendar.token.mjs +0 -12
- package/esm2022/calendar/lib/i18n/calendar-i18n.mjs +0 -33
- package/esm2022/calendar/spartan-ng-brain-calendar.mjs +0 -5
- package/esm2022/checkbox/index.mjs +0 -18
- package/esm2022/checkbox/lib/brn-checkbox.component.mjs +0 -248
- package/esm2022/checkbox/spartan-ng-brain-checkbox.mjs +0 -5
- package/esm2022/collapsible/index.mjs +0 -30
- package/esm2022/collapsible/lib/brn-collapsible-content.component.mjs +0 -62
- package/esm2022/collapsible/lib/brn-collapsible-trigger.directive.mjs +0 -35
- package/esm2022/collapsible/lib/brn-collapsible.component.mjs +0 -33
- package/esm2022/collapsible/spartan-ng-brain-collapsible.mjs +0 -5
- package/esm2022/command/index.mjs +0 -48
- package/esm2022/command/lib/brn-command-empty.directive.mjs +0 -30
- package/esm2022/command/lib/brn-command-group.directive.mjs +0 -29
- package/esm2022/command/lib/brn-command-item.directive.mjs +0 -92
- package/esm2022/command/lib/brn-command-item.token.mjs +0 -6
- package/esm2022/command/lib/brn-command-list.directive.mjs +0 -21
- package/esm2022/command/lib/brn-command-search-input.directive.mjs +0 -81
- package/esm2022/command/lib/brn-command-search-input.token.mjs +0 -6
- package/esm2022/command/lib/brn-command.directive.mjs +0 -81
- package/esm2022/command/lib/brn-command.token.mjs +0 -9
- package/esm2022/command/spartan-ng-brain-command.mjs +0 -5
- package/esm2022/core/helpers/create-injection-token.mjs +0 -15
- package/esm2022/core/helpers/custom-element-class-settable.mjs +0 -3
- package/esm2022/core/helpers/dev-mode.mjs +0 -6
- package/esm2022/core/helpers/exposes-side.mjs +0 -3
- package/esm2022/core/helpers/exposes-state.mjs +0 -3
- package/esm2022/core/helpers/hlm.mjs +0 -6
- package/esm2022/core/helpers/table-classes-settable.mjs +0 -3
- package/esm2022/core/helpers/zone-free.mjs +0 -15
- package/esm2022/core/index.mjs +0 -8
- package/esm2022/core/spartan-ng-brain-core.mjs +0 -5
- package/esm2022/date-time/index.mjs +0 -3
- package/esm2022/date-time/lib/date-adapter.mjs +0 -16
- package/esm2022/date-time/lib/native-date-adapter.mjs +0 -155
- package/esm2022/date-time/spartan-ng-brain-date-time.mjs +0 -5
- package/esm2022/date-time-luxon/index.mjs +0 -2
- package/esm2022/date-time-luxon/lib/date-adapter.mjs +0 -85
- package/esm2022/date-time-luxon/spartan-ng-brain-date-time-luxon.mjs +0 -5
- package/esm2022/dialog/index.mjs +0 -56
- package/esm2022/dialog/lib/brn-dialog-close.directive.mjs +0 -24
- package/esm2022/dialog/lib/brn-dialog-content.directive.mjs +0 -41
- package/esm2022/dialog/lib/brn-dialog-description.directive.mjs +0 -25
- package/esm2022/dialog/lib/brn-dialog-options.mjs +0 -19
- package/esm2022/dialog/lib/brn-dialog-overlay.component.mjs +0 -33
- package/esm2022/dialog/lib/brn-dialog-ref.mjs +0 -54
- package/esm2022/dialog/lib/brn-dialog-state.mjs +0 -2
- package/esm2022/dialog/lib/brn-dialog-title.directive.mjs +0 -25
- package/esm2022/dialog/lib/brn-dialog-token.mjs +0 -25
- package/esm2022/dialog/lib/brn-dialog-trigger.directive.mjs +0 -47
- package/esm2022/dialog/lib/brn-dialog-utils.mjs +0 -12
- package/esm2022/dialog/lib/brn-dialog.component.mjs +0 -179
- package/esm2022/dialog/lib/brn-dialog.service.mjs +0 -128
- package/esm2022/dialog/spartan-ng-brain-dialog.mjs +0 -5
- package/esm2022/form-field/index.mjs +0 -2
- package/esm2022/form-field/lib/brn-form-field-control.mjs +0 -14
- package/esm2022/form-field/spartan-ng-brain-form-field.mjs +0 -5
- package/esm2022/forms/index.mjs +0 -4
- package/esm2022/forms/lib/control-value-accessor.mjs +0 -2
- package/esm2022/forms/lib/error-options.mjs +0 -26
- package/esm2022/forms/lib/error-state-tracker.mjs +0 -29
- package/esm2022/forms/spartan-ng-brain-forms.mjs +0 -5
- package/esm2022/hover-card/index.mjs +0 -29
- package/esm2022/hover-card/lib/brn-hover-card-content.service.mjs +0 -197
- package/esm2022/hover-card/lib/brn-hover-card.component.mjs +0 -28
- package/esm2022/hover-card/lib/createHoverObservable.mjs +0 -20
- package/esm2022/hover-card/spartan-ng-brain-hover-card.mjs +0 -5
- package/esm2022/index.mjs +0 -3
- package/esm2022/label/index.mjs +0 -17
- package/esm2022/label/lib/brn-label.directive.mjs +0 -49
- package/esm2022/label/spartan-ng-brain-label.mjs +0 -5
- package/esm2022/menu/index.mjs +0 -100
- package/esm2022/menu/lib/brn-context-menu-trigger.directive.mjs +0 -40
- package/esm2022/menu/lib/brn-menu-align.mjs +0 -15
- package/esm2022/menu/lib/brn-menu-bar.directive.mjs +0 -17
- package/esm2022/menu/lib/brn-menu-group.directive.mjs +0 -17
- package/esm2022/menu/lib/brn-menu-item-checkbox.directive.mjs +0 -30
- package/esm2022/menu/lib/brn-menu-item-radio.directive.mjs +0 -30
- package/esm2022/menu/lib/brn-menu-item.directive.mjs +0 -27
- package/esm2022/menu/lib/brn-menu-trigger.directive.mjs +0 -42
- package/esm2022/menu/lib/brn-menu.directive.mjs +0 -56
- package/esm2022/menu/spartan-ng-brain-menu.mjs +0 -5
- package/esm2022/popover/index.mjs +0 -35
- package/esm2022/popover/lib/brn-popover-close.directive.mjs +0 -15
- package/esm2022/popover/lib/brn-popover-content.directive.mjs +0 -17
- package/esm2022/popover/lib/brn-popover-trigger.directive.mjs +0 -43
- package/esm2022/popover/lib/brn-popover.component.mjs +0 -81
- package/esm2022/popover/spartan-ng-brain-popover.mjs +0 -5
- package/esm2022/progress/index.mjs +0 -21
- package/esm2022/progress/lib/brn-progress-indicator.component.mjs +0 -22
- package/esm2022/progress/lib/brn-progress.component.mjs +0 -61
- package/esm2022/progress/lib/brn-progress.token.mjs +0 -9
- package/esm2022/progress/spartan-ng-brain-progress.mjs +0 -5
- package/esm2022/radio-group/index.mjs +0 -20
- package/esm2022/radio-group/lib/brn-radio-group.directive.mjs +0 -90
- package/esm2022/radio-group/lib/brn-radio-group.token.mjs +0 -9
- package/esm2022/radio-group/lib/brn-radio.component.mjs +0 -191
- package/esm2022/radio-group/spartan-ng-brain-radio-group.mjs +0 -5
- package/esm2022/select/index.mjs +0 -66
- package/esm2022/select/lib/brn-select-content.component.mjs +0 -224
- package/esm2022/select/lib/brn-select-content.token.mjs +0 -9
- package/esm2022/select/lib/brn-select-group.directive.mjs +0 -19
- package/esm2022/select/lib/brn-select-label.directive.mjs +0 -23
- package/esm2022/select/lib/brn-select-option.directive.mjs +0 -69
- package/esm2022/select/lib/brn-select-placeholder.directive.mjs +0 -16
- package/esm2022/select/lib/brn-select-trigger.directive.mjs +0 -67
- package/esm2022/select/lib/brn-select-value.component.mjs +0 -68
- package/esm2022/select/lib/brn-select-value.directive.mjs +0 -16
- package/esm2022/select/lib/brn-select.component.mjs +0 -272
- package/esm2022/select/lib/brn-select.token.mjs +0 -9
- package/esm2022/select/spartan-ng-brain-select.mjs +0 -5
- package/esm2022/separator/index.mjs +0 -17
- package/esm2022/separator/lib/brn-separator.component.mjs +0 -24
- package/esm2022/separator/spartan-ng-brain-separator.mjs +0 -5
- package/esm2022/sheet/index.mjs +0 -50
- package/esm2022/sheet/lib/brn-sheet-close.directive.mjs +0 -15
- package/esm2022/sheet/lib/brn-sheet-content.directive.mjs +0 -25
- package/esm2022/sheet/lib/brn-sheet-description.directive.mjs +0 -18
- package/esm2022/sheet/lib/brn-sheet-overlay.component.mjs +0 -20
- package/esm2022/sheet/lib/brn-sheet-title.directive.mjs +0 -18
- package/esm2022/sheet/lib/brn-sheet-trigger.directive.mjs +0 -25
- package/esm2022/sheet/lib/brn-sheet.component.mjs +0 -57
- package/esm2022/sheet/spartan-ng-brain-sheet.mjs +0 -5
- package/esm2022/slider/index.mjs +0 -13
- package/esm2022/slider/lib/brn-slider-thumb.directive.mjs +0 -41
- package/esm2022/slider/lib/brn-slider-tick-mark.directive.mjs +0 -37
- package/esm2022/slider/lib/brn-slider-track-active-fill.directive.mjs +0 -29
- package/esm2022/slider/lib/brn-slider-track.directive.mjs +0 -297
- package/esm2022/slider/spartan-ng-brain-slider.mjs +0 -5
- package/esm2022/spartan-ng-brain.mjs +0 -5
- package/esm2022/switch/index.mjs +0 -20
- package/esm2022/switch/lib/brn-switch-thumb.component.mjs +0 -16
- package/esm2022/switch/lib/brn-switch.component.mjs +0 -236
- package/esm2022/switch/spartan-ng-brain-switch.mjs +0 -5
- package/esm2022/table/index.mjs +0 -47
- package/esm2022/table/lib/brn-cell-def.directive.mjs +0 -22
- package/esm2022/table/lib/brn-column-def.component.mjs +0 -82
- package/esm2022/table/lib/brn-column-manager.mjs +0 -61
- package/esm2022/table/lib/brn-footer-def.directive.mjs +0 -22
- package/esm2022/table/lib/brn-header-def.directive.mjs +0 -22
- package/esm2022/table/lib/brn-paginator.directive.mjs +0 -111
- package/esm2022/table/lib/brn-table.component.mjs +0 -169
- package/esm2022/table/spartan-ng-brain-table.mjs +0 -5
- package/esm2022/tabs/index.mjs +0 -32
- package/esm2022/tabs/lib/brn-tabs-list.directive.mjs +0 -66
- package/esm2022/tabs/lib/brn-tabs-paginated-list.directive.mjs +0 -525
- package/esm2022/tabs/lib/brn-tabs-trigger.directive.mjs +0 -136
- package/esm2022/tabs/spartan-ng-brain-tabs.mjs +0 -5
- package/esm2022/toggle/index.mjs +0 -31
- package/esm2022/toggle/lib/brn-toggle-group.component.mjs +0 -159
- package/esm2022/toggle/lib/brn-toggle-group.token.mjs +0 -9
- package/esm2022/toggle/lib/brn-toggle.directive.mjs +0 -65
- package/esm2022/toggle/spartan-ng-brain-toggle.mjs +0 -5
- package/esm2022/tooltip/index.mjs +0 -36
- package/esm2022/tooltip/lib/brn-tooltip-content.component.mjs +0 -221
- package/esm2022/tooltip/lib/brn-tooltip-content.directive.mjs +0 -22
- package/esm2022/tooltip/lib/brn-tooltip-trigger.directive.mjs +0 -629
- package/esm2022/tooltip/lib/brn-tooltip.directive.mjs +0 -15
- package/esm2022/tooltip/lib/brn-tooltip.token.mjs +0 -18
- package/esm2022/tooltip/lib/computed-previous.mjs +0 -46
- package/esm2022/tooltip/spartan-ng-brain-tooltip.mjs +0 -5
|
@@ -1,629 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* We are building on shoulders of giants here and adapt the implementation provided by the incredible Angular
|
|
3
|
-
* team: https://github.com/angular/components/blob/main/src/material/tooltip/tooltip.ts
|
|
4
|
-
* Check them out! Give them a try! Leave a star! Their work is incredible!
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* @license
|
|
8
|
-
* Copyright Google LLC All Rights Reserved.
|
|
9
|
-
*
|
|
10
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
11
|
-
* found in the LICENSE file at https://angular.io/license
|
|
12
|
-
*/
|
|
13
|
-
import { AriaDescriber, FocusMonitor } from '@angular/cdk/a11y';
|
|
14
|
-
import { Directionality } from '@angular/cdk/bidi';
|
|
15
|
-
import { hasModifierKey } from '@angular/cdk/keycodes';
|
|
16
|
-
import { Overlay, ScrollDispatcher, } from '@angular/cdk/overlay';
|
|
17
|
-
import { normalizePassiveListenerOptions, Platform } from '@angular/cdk/platform';
|
|
18
|
-
import { ComponentPortal } from '@angular/cdk/portal';
|
|
19
|
-
import { DOCUMENT } from '@angular/common';
|
|
20
|
-
import { booleanAttribute, computed, Directive, effect, ElementRef, inject, InjectionToken, input, isDevMode, NgZone, numberAttribute, untracked, ViewContainerRef, } from '@angular/core';
|
|
21
|
-
import { brnDevMode } from '@spartan-ng/brain/core';
|
|
22
|
-
import { Subject } from 'rxjs';
|
|
23
|
-
import { take, takeUntil } from 'rxjs/operators';
|
|
24
|
-
import { BrnTooltipContentComponent } from './brn-tooltip-content.component';
|
|
25
|
-
import { BrnTooltipDirective } from './brn-tooltip.directive';
|
|
26
|
-
import { injectBrnTooltipDefaultOptions } from './brn-tooltip.token';
|
|
27
|
-
import { computedPrevious } from './computed-previous';
|
|
28
|
-
import * as i0 from "@angular/core";
|
|
29
|
-
/** Time in ms to throttle repositioning after scroll events. */
|
|
30
|
-
export const SCROLL_THROTTLE_MS = 20;
|
|
31
|
-
export function getBrnTooltipInvalidPositionError(position) {
|
|
32
|
-
return Error(`Tooltip position "${position}" is invalid.`);
|
|
33
|
-
}
|
|
34
|
-
/** Injection token that determines the scroll handling while a tooltip is visible. */
|
|
35
|
-
export const BRN_TOOLTIP_SCROLL_STRATEGY = new InjectionToken('brn-tooltip-scroll-strategy');
|
|
36
|
-
export const BRN_TOOLTIP_SCROLL_STRATEGY_FACTORY_PROVIDER = {
|
|
37
|
-
provide: BRN_TOOLTIP_SCROLL_STRATEGY,
|
|
38
|
-
deps: [Overlay],
|
|
39
|
-
useFactory: (overlay) => () => overlay.scrollStrategies.reposition({ scrollThrottle: SCROLL_THROTTLE_MS }),
|
|
40
|
-
};
|
|
41
|
-
const PANEL_CLASS = 'tooltip-panel';
|
|
42
|
-
/** Options used to bind passive event listeners. */
|
|
43
|
-
const passiveListenerOptions = normalizePassiveListenerOptions({ passive: true });
|
|
44
|
-
/**
|
|
45
|
-
* Time between the user putting the pointer on a tooltip
|
|
46
|
-
* trigger and the long press event being fired.
|
|
47
|
-
*/
|
|
48
|
-
const LONGPRESS_DELAY = 500;
|
|
49
|
-
// These constants were taken from MDC's `numbers` object.
|
|
50
|
-
const MIN_VIEWPORT_TOOLTIP_THRESHOLD = 8;
|
|
51
|
-
const UNBOUNDED_ANCHOR_GAP = 8;
|
|
52
|
-
export class BrnTooltipTriggerDirective {
|
|
53
|
-
_tooltipDirective = inject(BrnTooltipDirective, { optional: true });
|
|
54
|
-
_tooltipComponent = BrnTooltipContentComponent;
|
|
55
|
-
_cssClassPrefix = 'brn';
|
|
56
|
-
_destroyed = new Subject();
|
|
57
|
-
_passiveListeners = [];
|
|
58
|
-
_defaultOptions = injectBrnTooltipDefaultOptions();
|
|
59
|
-
_overlay = inject(Overlay);
|
|
60
|
-
_elementRef = inject((ElementRef));
|
|
61
|
-
_scrollDispatcher = inject(ScrollDispatcher);
|
|
62
|
-
_viewContainerRef = inject(ViewContainerRef);
|
|
63
|
-
_ngZone = inject(NgZone);
|
|
64
|
-
_platform = inject(Platform);
|
|
65
|
-
_ariaDescriber = inject(AriaDescriber);
|
|
66
|
-
_focusMonitor = inject(FocusMonitor);
|
|
67
|
-
_dir = inject(Directionality);
|
|
68
|
-
_scrollStrategy = inject(BRN_TOOLTIP_SCROLL_STRATEGY);
|
|
69
|
-
_document = inject(DOCUMENT);
|
|
70
|
-
_portal;
|
|
71
|
-
_viewInitialized = false;
|
|
72
|
-
_pointerExitEventsInitialized = false;
|
|
73
|
-
_viewportMargin = 8;
|
|
74
|
-
_currentPosition;
|
|
75
|
-
_touchstartTimeout;
|
|
76
|
-
_overlayRef = null;
|
|
77
|
-
_tooltipInstance = null;
|
|
78
|
-
/** Allows the user to define the position of the tooltip relative to the parent element */
|
|
79
|
-
position = input(this._defaultOptions?.position ?? 'above');
|
|
80
|
-
/**
|
|
81
|
-
* Whether tooltip should be relative to the click or touch origin
|
|
82
|
-
* instead of outside the element bounding box.
|
|
83
|
-
*/
|
|
84
|
-
positionAtOrigin = input(this._defaultOptions?.positionAtOrigin ?? false, {
|
|
85
|
-
transform: booleanAttribute,
|
|
86
|
-
});
|
|
87
|
-
/** Disables the display of the tooltip. */
|
|
88
|
-
brnTooltipDisabled = input(false, { transform: booleanAttribute });
|
|
89
|
-
/** The default delay in ms before showing the tooltip after show is called */
|
|
90
|
-
showDelay = input(this._defaultOptions?.showDelay ?? 0, { transform: numberAttribute });
|
|
91
|
-
/** The default delay in ms before hiding the tooltip after hide is called */
|
|
92
|
-
hideDelay = input(this._defaultOptions?.hideDelay ?? 0, { transform: numberAttribute });
|
|
93
|
-
/** The default duration in ms that exit animation takes before hiding */
|
|
94
|
-
exitAnimationDuration = input(this._defaultOptions?.exitAnimationDuration ?? 0, {
|
|
95
|
-
transform: numberAttribute,
|
|
96
|
-
});
|
|
97
|
-
/** The default delay in ms before hiding the tooltip after hide is called */
|
|
98
|
-
tooltipContentClasses = input(this._defaultOptions?.tooltipContentClasses ?? '');
|
|
99
|
-
/**
|
|
100
|
-
* How touch gestures should be handled by the tooltip. On touch devices the tooltip directive
|
|
101
|
-
* uses a long press gesture to show and hide, however it can conflict with the native browser
|
|
102
|
-
* gestures. To work around the conflict, Angular Material disables native gestures on the
|
|
103
|
-
* trigger, but that might not be desirable on particular elements (e.g. inputs and draggable
|
|
104
|
-
* elements). The different values for this option configure the touch event handling as follows:
|
|
105
|
-
* - `auto` - Enables touch gestures for all elements, but tries to avoid conflicts with native
|
|
106
|
-
* browser gestures on particular elements. In particular, it allows text selection on inputs
|
|
107
|
-
* and textareas, and preserves the native browser dragging on elements marked as `draggable`.
|
|
108
|
-
* - `on` - Enables touch gestures for all elements and disables native
|
|
109
|
-
* browser gestures with no exceptions.
|
|
110
|
-
* - `off` - Disables touch gestures. Note that this will prevent the tooltip from
|
|
111
|
-
* showing on touch devices.
|
|
112
|
-
*/
|
|
113
|
-
touchGestures = input(this._defaultOptions?.touchGestures ?? 'auto');
|
|
114
|
-
/** The message to be used to describe the aria in the tooltip */
|
|
115
|
-
ariaDescribedBy = input('', { alias: 'aria-describedby' });
|
|
116
|
-
ariaDescribedByPrevious = computedPrevious(this.ariaDescribedBy);
|
|
117
|
-
/** The content to be displayed in the tooltip */
|
|
118
|
-
brnTooltipTrigger = input(null);
|
|
119
|
-
brnTooltipTriggerState = computed(() => {
|
|
120
|
-
if (this._tooltipDirective) {
|
|
121
|
-
return this._tooltipDirective.tooltipTemplate();
|
|
122
|
-
}
|
|
123
|
-
return this.brnTooltipTrigger();
|
|
124
|
-
});
|
|
125
|
-
constructor() {
|
|
126
|
-
this._dir.change.pipe(takeUntil(this._destroyed)).subscribe(() => {
|
|
127
|
-
if (this._overlayRef) {
|
|
128
|
-
this._updatePosition(this._overlayRef);
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
this._viewportMargin = MIN_VIEWPORT_TOOLTIP_THRESHOLD;
|
|
132
|
-
this._initBrnTooltipTriggerEffect();
|
|
133
|
-
this._initAriaDescribedByPreviousEffect();
|
|
134
|
-
this._initTooltipContentClassesEffect();
|
|
135
|
-
this._initPositionEffect();
|
|
136
|
-
this._initPositionAtOriginEffect();
|
|
137
|
-
this._initBrnTooltipDisabledEffect();
|
|
138
|
-
this._initExitAnimationDurationEffect();
|
|
139
|
-
this._initHideDelayEffect();
|
|
140
|
-
}
|
|
141
|
-
_initPositionEffect() {
|
|
142
|
-
effect(() => {
|
|
143
|
-
if (this._overlayRef) {
|
|
144
|
-
this._updatePosition(this._overlayRef);
|
|
145
|
-
this._tooltipInstance?.show(0);
|
|
146
|
-
this._overlayRef.updatePosition();
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
_initBrnTooltipDisabledEffect() {
|
|
151
|
-
effect(() => {
|
|
152
|
-
if (this.brnTooltipDisabled()) {
|
|
153
|
-
this.hide(0);
|
|
154
|
-
}
|
|
155
|
-
else {
|
|
156
|
-
this._setupPointerEnterEventsIfNeeded();
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
_initPositionAtOriginEffect() {
|
|
161
|
-
effect(() => {
|
|
162
|
-
// Needed that the effect got triggered
|
|
163
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
164
|
-
const _ = this.positionAtOrigin();
|
|
165
|
-
this._detach();
|
|
166
|
-
this._overlayRef = null;
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
_initTooltipContentClassesEffect() {
|
|
170
|
-
effect(() => {
|
|
171
|
-
if (this._tooltipInstance) {
|
|
172
|
-
this._tooltipInstance._tooltipClasses.set(this.tooltipContentClasses() ?? '');
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
_initAriaDescribedByPreviousEffect() {
|
|
177
|
-
effect(() => {
|
|
178
|
-
const ariaDescribedBy = this.ariaDescribedBy();
|
|
179
|
-
this._ariaDescriber.removeDescription(this._elementRef.nativeElement, untracked(() => this.ariaDescribedByPrevious()), 'tooltip');
|
|
180
|
-
if (ariaDescribedBy && !this._isTooltipVisible()) {
|
|
181
|
-
this._ngZone.runOutsideAngular(() => {
|
|
182
|
-
// The `AriaDescriber` has some functionality that avoids adding a description if it's the
|
|
183
|
-
// same as the `aria-label` of an element, however we can't know whether the tooltip trigger
|
|
184
|
-
// has a data-bound `aria-label` or when it'll be set for the first time. We can avoid the
|
|
185
|
-
// issue by deferring the description by a tick so Angular has time to set the `aria-label`.
|
|
186
|
-
Promise.resolve().then(() => {
|
|
187
|
-
this._ariaDescriber.describe(this._elementRef.nativeElement, ariaDescribedBy, 'tooltip');
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
_initBrnTooltipTriggerEffect() {
|
|
194
|
-
effect(() => {
|
|
195
|
-
const brnTooltipTriggerState = this.brnTooltipTriggerState();
|
|
196
|
-
const isTooltipVisible = this._isTooltipVisible();
|
|
197
|
-
untracked(() => {
|
|
198
|
-
if (!brnTooltipTriggerState && isTooltipVisible) {
|
|
199
|
-
this.hide(0);
|
|
200
|
-
}
|
|
201
|
-
else {
|
|
202
|
-
this._setupPointerEnterEventsIfNeeded();
|
|
203
|
-
this._updateTooltipContent();
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
_initExitAnimationDurationEffect() {
|
|
209
|
-
effect(() => {
|
|
210
|
-
if (this._tooltipInstance) {
|
|
211
|
-
this._tooltipInstance._exitAnimationDuration = this.exitAnimationDuration();
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
_initHideDelayEffect() {
|
|
216
|
-
effect(() => {
|
|
217
|
-
if (this._tooltipInstance) {
|
|
218
|
-
this._tooltipInstance._mouseLeaveHideDelay = this.hideDelay();
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
ngAfterViewInit() {
|
|
223
|
-
// This needs to happen after view init so the initial values for all inputs have been set.
|
|
224
|
-
this._viewInitialized = true;
|
|
225
|
-
this._setupPointerEnterEventsIfNeeded();
|
|
226
|
-
this._focusMonitor
|
|
227
|
-
.monitor(this._elementRef)
|
|
228
|
-
.pipe(takeUntil(this._destroyed))
|
|
229
|
-
.subscribe((origin) => {
|
|
230
|
-
// Note that the focus monitor runs outside the Angular zone.
|
|
231
|
-
if (!origin) {
|
|
232
|
-
this._ngZone.run(() => this.hide(0));
|
|
233
|
-
}
|
|
234
|
-
else if (origin === 'keyboard') {
|
|
235
|
-
this._ngZone.run(() => this.show());
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
if (brnDevMode && !this.ariaDescribedBy()) {
|
|
239
|
-
console.warn('BrnTooltip: "aria-describedby" attribute is required for accessibility');
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Dispose the tooltip when destroyed.
|
|
244
|
-
*/
|
|
245
|
-
ngOnDestroy() {
|
|
246
|
-
const nativeElement = this._elementRef.nativeElement;
|
|
247
|
-
clearTimeout(this._touchstartTimeout);
|
|
248
|
-
if (this._overlayRef) {
|
|
249
|
-
this._overlayRef.dispose();
|
|
250
|
-
this._tooltipInstance = null;
|
|
251
|
-
}
|
|
252
|
-
// Clean up the event listeners set in the constructor
|
|
253
|
-
this._passiveListeners.forEach(([event, listener]) => nativeElement.removeEventListener(event, listener, passiveListenerOptions));
|
|
254
|
-
this._passiveListeners.length = 0;
|
|
255
|
-
this._destroyed.next();
|
|
256
|
-
this._destroyed.complete();
|
|
257
|
-
this._ariaDescriber.removeDescription(nativeElement, this.ariaDescribedBy(), 'tooltip');
|
|
258
|
-
this._focusMonitor.stopMonitoring(nativeElement);
|
|
259
|
-
}
|
|
260
|
-
/** Shows the tooltip after the delay in ms, defaults to tooltip-delay-show or 0ms if no input */
|
|
261
|
-
show(delay = this.showDelay(), origin) {
|
|
262
|
-
if (this.brnTooltipDisabled() || this._isTooltipVisible()) {
|
|
263
|
-
this._tooltipInstance?._cancelPendingAnimations();
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
const overlayRef = this._createOverlay(origin);
|
|
267
|
-
this._detach();
|
|
268
|
-
this._portal = this._portal || new ComponentPortal(this._tooltipComponent, this._viewContainerRef);
|
|
269
|
-
const instance = (this._tooltipInstance = overlayRef.attach(this._portal).instance);
|
|
270
|
-
instance._triggerElement = this._elementRef.nativeElement;
|
|
271
|
-
instance._mouseLeaveHideDelay = this.hideDelay();
|
|
272
|
-
instance._tooltipClasses.set(this.tooltipContentClasses());
|
|
273
|
-
instance._exitAnimationDuration = this.exitAnimationDuration();
|
|
274
|
-
instance.side.set(this._currentPosition ?? 'above');
|
|
275
|
-
instance.afterHidden.pipe(takeUntil(this._destroyed)).subscribe(() => this._detach());
|
|
276
|
-
this._updateTooltipContent();
|
|
277
|
-
instance.show(delay);
|
|
278
|
-
}
|
|
279
|
-
/** Hides the tooltip after the delay in ms, defaults to tooltip-delay-hide or 0ms if no input */
|
|
280
|
-
hide(delay = this.hideDelay(), exitAnimationDuration = this.exitAnimationDuration()) {
|
|
281
|
-
const instance = this._tooltipInstance;
|
|
282
|
-
if (instance) {
|
|
283
|
-
if (instance.isVisible()) {
|
|
284
|
-
instance.hide(delay, exitAnimationDuration);
|
|
285
|
-
}
|
|
286
|
-
else {
|
|
287
|
-
instance._cancelPendingAnimations();
|
|
288
|
-
this._detach();
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
toggle(origin) {
|
|
293
|
-
this._isTooltipVisible() ? this.hide() : this.show(undefined, origin);
|
|
294
|
-
}
|
|
295
|
-
_isTooltipVisible() {
|
|
296
|
-
return !!this._tooltipInstance && this._tooltipInstance.isVisible();
|
|
297
|
-
}
|
|
298
|
-
_createOverlay(origin) {
|
|
299
|
-
if (this._overlayRef) {
|
|
300
|
-
const existingStrategy = this._overlayRef.getConfig().positionStrategy;
|
|
301
|
-
if ((!this.positionAtOrigin() || !origin) && existingStrategy._origin instanceof ElementRef) {
|
|
302
|
-
return this._overlayRef;
|
|
303
|
-
}
|
|
304
|
-
this._detach();
|
|
305
|
-
}
|
|
306
|
-
const scrollableAncestors = this._scrollDispatcher.getAncestorScrollContainers(this._elementRef);
|
|
307
|
-
// Create connected position strategy that listens for scroll events to reposition.
|
|
308
|
-
const strategy = this._overlay
|
|
309
|
-
.position()
|
|
310
|
-
.flexibleConnectedTo(this.positionAtOrigin() ? origin || this._elementRef : this._elementRef)
|
|
311
|
-
.withTransformOriginOn(`.${this._cssClassPrefix}-tooltip`)
|
|
312
|
-
.withFlexibleDimensions(false)
|
|
313
|
-
.withViewportMargin(this._viewportMargin)
|
|
314
|
-
.withScrollableContainers(scrollableAncestors);
|
|
315
|
-
strategy.positionChanges.pipe(takeUntil(this._destroyed)).subscribe((change) => {
|
|
316
|
-
this._updateCurrentPositionClass(change.connectionPair);
|
|
317
|
-
if (this._tooltipInstance) {
|
|
318
|
-
if (change.scrollableViewProperties.isOverlayClipped && this._tooltipInstance.isVisible()) {
|
|
319
|
-
// After position changes occur and the overlay is clipped by
|
|
320
|
-
// a parent scrollable then close the tooltip.
|
|
321
|
-
this._ngZone.run(() => this.hide(0));
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
});
|
|
325
|
-
this._overlayRef = this._overlay.create({
|
|
326
|
-
direction: this._dir,
|
|
327
|
-
positionStrategy: strategy,
|
|
328
|
-
panelClass: `${this._cssClassPrefix}-${PANEL_CLASS}`,
|
|
329
|
-
scrollStrategy: this._scrollStrategy(),
|
|
330
|
-
});
|
|
331
|
-
this._updatePosition(this._overlayRef);
|
|
332
|
-
this._overlayRef
|
|
333
|
-
.detachments()
|
|
334
|
-
.pipe(takeUntil(this._destroyed))
|
|
335
|
-
.subscribe(() => this._detach());
|
|
336
|
-
this._overlayRef
|
|
337
|
-
.outsidePointerEvents()
|
|
338
|
-
.pipe(takeUntil(this._destroyed))
|
|
339
|
-
.subscribe(() => this._tooltipInstance?._handleBodyInteraction());
|
|
340
|
-
this._overlayRef
|
|
341
|
-
.keydownEvents()
|
|
342
|
-
.pipe(takeUntil(this._destroyed))
|
|
343
|
-
.subscribe((event) => {
|
|
344
|
-
if (this._isTooltipVisible() && event.key === 'Escape' && !hasModifierKey(event)) {
|
|
345
|
-
event.preventDefault();
|
|
346
|
-
event.stopPropagation();
|
|
347
|
-
this._ngZone.run(() => this.hide(0));
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
if (this._defaultOptions?.disableTooltipInteractivity) {
|
|
351
|
-
this._overlayRef.addPanelClass(`${this._cssClassPrefix}-tooltip-panel-non-interactive`);
|
|
352
|
-
}
|
|
353
|
-
return this._overlayRef;
|
|
354
|
-
}
|
|
355
|
-
_detach() {
|
|
356
|
-
if (this._overlayRef?.hasAttached()) {
|
|
357
|
-
this._overlayRef.detach();
|
|
358
|
-
}
|
|
359
|
-
this._tooltipInstance = null;
|
|
360
|
-
}
|
|
361
|
-
_updatePosition(overlayRef) {
|
|
362
|
-
const position = overlayRef.getConfig().positionStrategy;
|
|
363
|
-
const origin = this._getOrigin();
|
|
364
|
-
const overlay = this._getOverlayPosition();
|
|
365
|
-
position.withPositions([
|
|
366
|
-
this._addOffset({ ...origin.main, ...overlay.main }),
|
|
367
|
-
this._addOffset({ ...origin.fallback, ...overlay.fallback }),
|
|
368
|
-
]);
|
|
369
|
-
}
|
|
370
|
-
/** Adds the configured offset to a position. Used as a hook for child classes. */
|
|
371
|
-
_addOffset(position) {
|
|
372
|
-
const offset = UNBOUNDED_ANCHOR_GAP;
|
|
373
|
-
const isLtr = !this._dir || this._dir.value === 'ltr';
|
|
374
|
-
if (position.originY === 'top') {
|
|
375
|
-
position.offsetY = -offset;
|
|
376
|
-
}
|
|
377
|
-
else if (position.originY === 'bottom') {
|
|
378
|
-
position.offsetY = offset;
|
|
379
|
-
}
|
|
380
|
-
else if (position.originX === 'start') {
|
|
381
|
-
position.offsetX = isLtr ? -offset : offset;
|
|
382
|
-
}
|
|
383
|
-
else if (position.originX === 'end') {
|
|
384
|
-
position.offsetX = isLtr ? offset : -offset;
|
|
385
|
-
}
|
|
386
|
-
return position;
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Returns the origin position and a fallback position based on the user's position preference.
|
|
390
|
-
* The fallback position is the inverse of the origin (e.g. `'below' -> 'above'`).
|
|
391
|
-
*/
|
|
392
|
-
_getOrigin() {
|
|
393
|
-
const isLtr = !this._dir || this._dir.value === 'ltr';
|
|
394
|
-
const position = this.position();
|
|
395
|
-
let originPosition;
|
|
396
|
-
if (position === 'above' || position === 'below') {
|
|
397
|
-
originPosition = { originX: 'center', originY: position === 'above' ? 'top' : 'bottom' };
|
|
398
|
-
}
|
|
399
|
-
else if (position === 'before' || (position === 'left' && isLtr) || (position === 'right' && !isLtr)) {
|
|
400
|
-
originPosition = { originX: 'start', originY: 'center' };
|
|
401
|
-
}
|
|
402
|
-
else if (position === 'after' || (position === 'right' && isLtr) || (position === 'left' && !isLtr)) {
|
|
403
|
-
originPosition = { originX: 'end', originY: 'center' };
|
|
404
|
-
}
|
|
405
|
-
else if (typeof isDevMode() === 'undefined' || isDevMode()) {
|
|
406
|
-
throw getBrnTooltipInvalidPositionError(position);
|
|
407
|
-
}
|
|
408
|
-
const { x, y } = this._invertPosition(originPosition.originX, originPosition.originY);
|
|
409
|
-
return {
|
|
410
|
-
main: originPosition,
|
|
411
|
-
fallback: { originX: x, originY: y },
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
/** Returns the overlay position and a fallback position based on the user's preference */
|
|
415
|
-
_getOverlayPosition() {
|
|
416
|
-
const isLtr = !this._dir || this._dir.value === 'ltr';
|
|
417
|
-
const position = this.position();
|
|
418
|
-
let overlayPosition;
|
|
419
|
-
if (position === 'above') {
|
|
420
|
-
overlayPosition = { overlayX: 'center', overlayY: 'bottom' };
|
|
421
|
-
}
|
|
422
|
-
else if (position === 'below') {
|
|
423
|
-
overlayPosition = { overlayX: 'center', overlayY: 'top' };
|
|
424
|
-
}
|
|
425
|
-
else if (position === 'before' || (position === 'left' && isLtr) || (position === 'right' && !isLtr)) {
|
|
426
|
-
overlayPosition = { overlayX: 'end', overlayY: 'center' };
|
|
427
|
-
}
|
|
428
|
-
else if (position === 'after' || (position === 'right' && isLtr) || (position === 'left' && !isLtr)) {
|
|
429
|
-
overlayPosition = { overlayX: 'start', overlayY: 'center' };
|
|
430
|
-
}
|
|
431
|
-
else if (typeof isDevMode() === 'undefined' || isDevMode()) {
|
|
432
|
-
throw getBrnTooltipInvalidPositionError(position);
|
|
433
|
-
}
|
|
434
|
-
const { x, y } = this._invertPosition(overlayPosition.overlayX, overlayPosition.overlayY);
|
|
435
|
-
return {
|
|
436
|
-
main: overlayPosition,
|
|
437
|
-
fallback: { overlayX: x, overlayY: y },
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
/** Updates the tooltip message and repositions the overlay according to the new message length */
|
|
441
|
-
_updateTooltipContent() {
|
|
442
|
-
// Must wait for the template to be painted to the tooltip so that the overlay can properly
|
|
443
|
-
// calculate the correct positioning based on the size of the tek-pate.
|
|
444
|
-
if (this._tooltipInstance) {
|
|
445
|
-
this._tooltipInstance.content = this.brnTooltipTriggerState();
|
|
446
|
-
this._tooltipInstance._markForCheck();
|
|
447
|
-
this._ngZone.onMicrotaskEmpty.pipe(take(1), takeUntil(this._destroyed)).subscribe(() => {
|
|
448
|
-
if (this._tooltipInstance) {
|
|
449
|
-
this._overlayRef?.updatePosition();
|
|
450
|
-
}
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
/** Inverts an overlay position. */
|
|
455
|
-
_invertPosition(x, y) {
|
|
456
|
-
if (this.position() === 'above' || this.position() === 'below') {
|
|
457
|
-
if (y === 'top') {
|
|
458
|
-
y = 'bottom';
|
|
459
|
-
}
|
|
460
|
-
else if (y === 'bottom') {
|
|
461
|
-
y = 'top';
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
else {
|
|
465
|
-
if (x === 'end') {
|
|
466
|
-
x = 'start';
|
|
467
|
-
}
|
|
468
|
-
else if (x === 'start') {
|
|
469
|
-
x = 'end';
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
return { x, y };
|
|
473
|
-
}
|
|
474
|
-
/** Updates the class on the overlay panel based on the current position of the tooltip. */
|
|
475
|
-
_updateCurrentPositionClass(connectionPair) {
|
|
476
|
-
const { overlayY, originX, originY } = connectionPair;
|
|
477
|
-
let newPosition;
|
|
478
|
-
// If the overlay is in the middle along the Y axis,
|
|
479
|
-
// it means that it's either before or after.
|
|
480
|
-
if (overlayY === 'center') {
|
|
481
|
-
// Note that since this information is used for styling, we want to
|
|
482
|
-
// resolve `start` and `end` to their real values, otherwise consumers
|
|
483
|
-
// would have to remember to do it themselves on each consumption.
|
|
484
|
-
if (this._dir && this._dir.value === 'rtl') {
|
|
485
|
-
newPosition = originX === 'end' ? 'left' : 'right';
|
|
486
|
-
}
|
|
487
|
-
else {
|
|
488
|
-
newPosition = originX === 'start' ? 'left' : 'right';
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
else {
|
|
492
|
-
newPosition = overlayY === 'bottom' && originY === 'top' ? 'above' : 'below';
|
|
493
|
-
}
|
|
494
|
-
if (newPosition !== this._currentPosition) {
|
|
495
|
-
this._tooltipInstance?.side.set(newPosition);
|
|
496
|
-
this._currentPosition = newPosition;
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
/** Binds the pointer events to the tooltip trigger. */
|
|
500
|
-
_setupPointerEnterEventsIfNeeded() {
|
|
501
|
-
// Optimization: Defer hooking up events if there's no content or the tooltip is disabled.
|
|
502
|
-
if (this.brnTooltipDisabled() ||
|
|
503
|
-
!this.brnTooltipTriggerState() ||
|
|
504
|
-
!this._viewInitialized ||
|
|
505
|
-
this._passiveListeners.length) {
|
|
506
|
-
return;
|
|
507
|
-
}
|
|
508
|
-
// The mouse events shouldn't be bound on mobile devices, because they can prevent the
|
|
509
|
-
// first tap from firing its click event or can cause the tooltip to open for clicks.
|
|
510
|
-
if (this._platformSupportsMouseEvents()) {
|
|
511
|
-
this._passiveListeners.push([
|
|
512
|
-
'mouseenter',
|
|
513
|
-
(event) => {
|
|
514
|
-
this._setupPointerExitEventsIfNeeded();
|
|
515
|
-
let point = undefined;
|
|
516
|
-
if (event.x !== undefined && event.y !== undefined) {
|
|
517
|
-
point = event;
|
|
518
|
-
}
|
|
519
|
-
this.show(undefined, point);
|
|
520
|
-
},
|
|
521
|
-
]);
|
|
522
|
-
}
|
|
523
|
-
else if (this.touchGestures() !== 'off') {
|
|
524
|
-
this._disableNativeGesturesIfNecessary();
|
|
525
|
-
this._passiveListeners.push([
|
|
526
|
-
'touchstart',
|
|
527
|
-
(event) => {
|
|
528
|
-
const touch = event.targetTouches?.[0];
|
|
529
|
-
const origin = touch ? { x: touch.clientX, y: touch.clientY } : undefined;
|
|
530
|
-
// Note that it's important that we don't `preventDefault` here,
|
|
531
|
-
// because it can prevent click events from firing on the element.
|
|
532
|
-
this._setupPointerExitEventsIfNeeded();
|
|
533
|
-
clearTimeout(this._touchstartTimeout);
|
|
534
|
-
this._touchstartTimeout = setTimeout(() => this.show(undefined, origin), LONGPRESS_DELAY);
|
|
535
|
-
},
|
|
536
|
-
]);
|
|
537
|
-
}
|
|
538
|
-
this._addListeners(this._passiveListeners);
|
|
539
|
-
}
|
|
540
|
-
_setupPointerExitEventsIfNeeded() {
|
|
541
|
-
if (this._pointerExitEventsInitialized) {
|
|
542
|
-
return;
|
|
543
|
-
}
|
|
544
|
-
this._pointerExitEventsInitialized = true;
|
|
545
|
-
const exitListeners = [];
|
|
546
|
-
if (this._platformSupportsMouseEvents()) {
|
|
547
|
-
exitListeners.push([
|
|
548
|
-
'mouseleave',
|
|
549
|
-
(event) => {
|
|
550
|
-
const newTarget = event.relatedTarget;
|
|
551
|
-
if (!newTarget || !this._overlayRef?.overlayElement.contains(newTarget)) {
|
|
552
|
-
this.hide();
|
|
553
|
-
}
|
|
554
|
-
},
|
|
555
|
-
], ['wheel', (event) => this._wheelListener(event)]);
|
|
556
|
-
}
|
|
557
|
-
else if (this.touchGestures() !== 'off') {
|
|
558
|
-
this._disableNativeGesturesIfNecessary();
|
|
559
|
-
const touchendListener = () => {
|
|
560
|
-
clearTimeout(this._touchstartTimeout);
|
|
561
|
-
this.hide(this._defaultOptions?.touchendHideDelay);
|
|
562
|
-
};
|
|
563
|
-
exitListeners.push(['touchend', touchendListener], ['touchcancel', touchendListener]);
|
|
564
|
-
}
|
|
565
|
-
this._addListeners(exitListeners);
|
|
566
|
-
this._passiveListeners.push(...exitListeners);
|
|
567
|
-
}
|
|
568
|
-
_addListeners(listeners) {
|
|
569
|
-
listeners.forEach(([event, listener]) => {
|
|
570
|
-
this._elementRef.nativeElement.addEventListener(event, listener, passiveListenerOptions);
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
_platformSupportsMouseEvents() {
|
|
574
|
-
return !this._platform.IOS && !this._platform.ANDROID;
|
|
575
|
-
}
|
|
576
|
-
/** Listener for the `wheel` event on the element. */
|
|
577
|
-
_wheelListener(event) {
|
|
578
|
-
if (this._isTooltipVisible()) {
|
|
579
|
-
const elementUnderPointer = this._document.elementFromPoint(event.clientX, event.clientY);
|
|
580
|
-
const element = this._elementRef.nativeElement;
|
|
581
|
-
// On non-touch devices we depend on the `mouseleave` event to close the tooltip, but it
|
|
582
|
-
// won't fire if the user scrolls away using the wheel without moving their cursor. We
|
|
583
|
-
// work around it by finding the element under the user's cursor and closing the tooltip
|
|
584
|
-
// if it's not the trigger.
|
|
585
|
-
if (elementUnderPointer !== element && !element.contains(elementUnderPointer)) {
|
|
586
|
-
this.hide();
|
|
587
|
-
}
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
/** Disables the native browser gestures, based on how the tooltip has been configured. */
|
|
591
|
-
_disableNativeGesturesIfNecessary() {
|
|
592
|
-
const gestures = this.touchGestures();
|
|
593
|
-
if (gestures !== 'off') {
|
|
594
|
-
const element = this._elementRef.nativeElement;
|
|
595
|
-
const style = element.style;
|
|
596
|
-
// If gestures are set to `auto`, we don't disable text selection on inputs and
|
|
597
|
-
// textareas, because it prevents the user from typing into them on iOS Safari.
|
|
598
|
-
if (gestures === 'on' || (element.nodeName !== 'INPUT' && element.nodeName !== 'TEXTAREA')) {
|
|
599
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
600
|
-
style.userSelect = style.msUserSelect = style.webkitUserSelect = style.MozUserSelect = 'none';
|
|
601
|
-
}
|
|
602
|
-
// If we have `auto` gestures and the element uses native HTML dragging,
|
|
603
|
-
// we don't set `-webkit-user-drag` because it prevents the native behavior.
|
|
604
|
-
if (gestures === 'on' || !element.draggable) {
|
|
605
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
606
|
-
style.webkitUserDrag = 'none';
|
|
607
|
-
}
|
|
608
|
-
style.touchAction = 'none';
|
|
609
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
610
|
-
style.webkitTapHighlightColor = 'transparent';
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnTooltipTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
614
|
-
/** @nocollapse */ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.5", type: BrnTooltipTriggerDirective, isStandalone: true, selector: "[brnTooltipTrigger]", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, positionAtOrigin: { classPropertyName: "positionAtOrigin", publicName: "positionAtOrigin", isSignal: true, isRequired: false, transformFunction: null }, brnTooltipDisabled: { classPropertyName: "brnTooltipDisabled", publicName: "brnTooltipDisabled", isSignal: true, isRequired: false, transformFunction: null }, showDelay: { classPropertyName: "showDelay", publicName: "showDelay", isSignal: true, isRequired: false, transformFunction: null }, hideDelay: { classPropertyName: "hideDelay", publicName: "hideDelay", isSignal: true, isRequired: false, transformFunction: null }, exitAnimationDuration: { classPropertyName: "exitAnimationDuration", publicName: "exitAnimationDuration", isSignal: true, isRequired: false, transformFunction: null }, tooltipContentClasses: { classPropertyName: "tooltipContentClasses", publicName: "tooltipContentClasses", isSignal: true, isRequired: false, transformFunction: null }, touchGestures: { classPropertyName: "touchGestures", publicName: "touchGestures", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedBy: { classPropertyName: "ariaDescribedBy", publicName: "aria-describedby", isSignal: true, isRequired: false, transformFunction: null }, brnTooltipTrigger: { classPropertyName: "brnTooltipTrigger", publicName: "brnTooltipTrigger", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.brn-tooltip-disabled": "brnTooltipDisabled()" }, classAttribute: "brn-tooltip-trigger" }, providers: [BRN_TOOLTIP_SCROLL_STRATEGY_FACTORY_PROVIDER], exportAs: ["brnTooltipTrigger"], ngImport: i0 });
|
|
615
|
-
}
|
|
616
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnTooltipTriggerDirective, decorators: [{
|
|
617
|
-
type: Directive,
|
|
618
|
-
args: [{
|
|
619
|
-
selector: '[brnTooltipTrigger]',
|
|
620
|
-
standalone: true,
|
|
621
|
-
exportAs: 'brnTooltipTrigger',
|
|
622
|
-
providers: [BRN_TOOLTIP_SCROLL_STRATEGY_FACTORY_PROVIDER],
|
|
623
|
-
host: {
|
|
624
|
-
class: 'brn-tooltip-trigger',
|
|
625
|
-
'[class.brn-tooltip-disabled]': 'brnTooltipDisabled()',
|
|
626
|
-
},
|
|
627
|
-
}]
|
|
628
|
-
}], ctorParameters: () => [] });
|
|
629
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJuLXRvb2x0aXAtdHJpZ2dlci5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9saWJzL2JyYWluL3Rvb2x0aXAvc3JjL2xpYi9icm4tdG9vbHRpcC10cmlnZ2VyLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBRUg7Ozs7OztHQU1HO0FBQ0gsT0FBTyxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbkQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3ZELE9BQU8sRUFNTixPQUFPLEVBR1AsZ0JBQWdCLEdBR2hCLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLCtCQUErQixFQUFFLFFBQVEsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2xGLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUVOLGdCQUFnQixFQUNoQixRQUFRLEVBQ1IsU0FBUyxFQUNULE1BQU0sRUFDTixVQUFVLEVBQ1YsTUFBTSxFQUNOLGNBQWMsRUFDZCxLQUFLLEVBQ0wsU0FBUyxFQUNULE1BQU0sRUFDTixlQUFlLEVBSWYsU0FBUyxFQUNULGdCQUFnQixHQUNoQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDcEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMvQixPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2pELE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FB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N0QsS0FBYSxDQUFDLGNBQWMsR0FBRyxNQUFNLENBQUM7WUFDeEMsQ0FBQztZQUVELEtBQUssQ0FBQyxXQUFXLEdBQUcsTUFBTSxDQUFDO1lBQzNCLDhEQUE4RDtZQUM3RCxLQUFhLENBQUMsdUJBQXVCLEdBQUcsYUFBYSxDQUFDO1FBQ3hELENBQUM7SUFDRixDQUFDOzBIQTVvQlcsMEJBQTBCOzhHQUExQiwwQkFBMEIseXBEQU4zQixDQUFDLDRDQUE0QyxDQUFDOzsyRkFNN0MsMEJBQTBCO2tCQVZ0QyxTQUFTO21CQUFDO29CQUNWLFFBQVEsRUFBRSxxQkFBcUI7b0JBQy9CLFVBQVUsRUFBRSxJQUFJO29CQUNoQixRQUFRLEVBQUUsbUJBQW1CO29CQUM3QixTQUFTLEVBQUUsQ0FBQyw0Q0FBNEMsQ0FBQztvQkFDekQsSUFBSSxFQUFFO3dCQUNMLEtBQUssRUFBRSxxQkFBcUI7d0JBQzVCLDhCQUE4QixFQUFFLHNCQUFzQjtxQkFDdEQ7aUJBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFdlIGFyZSBidWlsZGluZyBvbiBzaG91bGRlcnMgb2YgZ2lhbnRzIGhlcmUgYW5kIGFkYXB0IHRoZSBpbXBsZW1lbnRhdGlvbiBwcm92aWRlZCBieSB0aGUgaW5jcmVkaWJsZSBBbmd1bGFyXG4gKiB0ZWFtOiBodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9jb21wb25lbnRzL2Jsb2IvbWFpbi9zcmMvbWF0ZXJpYWwvdG9vbHRpcC90b29sdGlwLnRzXG4gKiBDaGVjayB0aGVtIG91dCEgR2l2ZSB0aGVtIGEgdHJ5ISBMZWF2ZSBhIHN0YXIhIFRoZWlyIHdvcmsgaXMgaW5jcmVkaWJsZSFcbiAqL1xuXG4vKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgR29vZ2xlIExMQyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cbmltcG9ydCB7IEFyaWFEZXNjcmliZXIsIEZvY3VzTW9uaXRvciB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9hMTF5JztcbmltcG9ydCB7IERpcmVjdGlvbmFsaXR5IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2JpZGknO1xuaW1wb3J0IHsgaGFzTW9kaWZpZXJLZXkgfSBmcm9tICdAYW5ndWxhci9jZGsva2V5Y29kZXMnO1xuaW1wb3J0IHtcblx0dHlwZSBDb25uZWN0ZWRQb3NpdGlvbixcblx0dHlwZSBDb25uZWN0aW9uUG9zaXRpb25QYWlyLFxuXHR0eXBlIEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneSxcblx0dHlwZSBIb3Jpem9udGFsQ29ubmVjdGlvblBvcyxcblx0dHlwZSBPcmlnaW5Db25uZWN0aW9uUG9zaXRpb24sXG5cdE92ZXJsYXksXG5cdHR5cGUgT3ZlcmxheUNvbm5lY3Rpb25Qb3NpdGlvbixcblx0dHlwZSBPdmVybGF5UmVmLFxuXHRTY3JvbGxEaXNwYXRjaGVyLFxuXHR0eXBlIFNjcm9sbFN0cmF0ZWd5LFxuXHR0eXBlIFZlcnRpY2FsQ29ubmVjdGlvblBvcyxcbn0gZnJvbSAnQGFuZ3VsYXIvY2RrL292ZXJsYXknO1xuaW1wb3J0IHsgbm9ybWFsaXplUGFzc2l2ZUxpc3RlbmVyT3B0aW9ucywgUGxhdGZvcm0gfSBmcm9tICdAYW5ndWxhci9jZGsvcGxhdGZvcm0nO1xuaW1wb3J0IHsgQ29tcG9uZW50UG9ydGFsIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3BvcnRhbCc7XG5pbXBvcnQgeyBET0NVTUVOVCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuXHR0eXBlIEFmdGVyVmlld0luaXQsXG5cdGJvb2xlYW5BdHRyaWJ1dGUsXG5cdGNvbXB1dGVkLFxuXHREaXJlY3RpdmUsXG5cdGVmZmVjdCxcblx0RWxlbWVudFJlZixcblx0aW5qZWN0LFxuXHRJbmplY3Rpb25Ub2tlbixcblx0aW5wdXQsXG5cdGlzRGV2TW9kZSxcblx0Tmdab25lLFxuXHRudW1iZXJBdHRyaWJ1dGUsXG5cdHR5cGUgT25EZXN0cm95LFxuXHR0eXBlIFByb3ZpZGVyLFxuXHR0eXBlIFRlbXBsYXRlUmVmLFxuXHR1bnRyYWNrZWQsXG5cdFZpZXdDb250YWluZXJSZWYsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgYnJuRGV2TW9kZSB9IGZyb20gJ0BzcGFydGFuLW5nL2JyYWluL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZSwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgQnJuVG9vbHRpcENvbnRlbnRDb21wb25lbnQgfSBmcm9tICcuL2Jybi10b29sdGlwLWNvbnRlbnQuY29tcG9uZW50JztcbmltcG9ydCB7IEJyblRvb2x0aXBEaXJlY3RpdmUgfSBmcm9tICcuL2Jybi10b29sdGlwLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBpbmplY3RCcm5Ub29sdGlwRGVmYXVsdE9wdGlvbnMgfSBmcm9tICcuL2Jybi10b29sdGlwLnRva2VuJztcbmltcG9ydCB7IGNvbXB1dGVkUHJldmlvdXMgfSBmcm9tICcuL2NvbXB1dGVkLXByZXZpb3VzJztcblxuZXhwb3J0IHR5cGUgVG9vbHRpcFBvc2l0aW9uID0gJ2xlZnQnIHwgJ3JpZ2h0JyB8ICdhYm92ZScgfCAnYmVsb3cnIHwgJ2JlZm9yZScgfCAnYWZ0ZXInO1xuZXhwb3J0IHR5cGUgVG9vbHRpcFRvdWNoR2VzdHVyZXMgPSAnYXV0bycgfCAnb24nIHwgJ29mZic7XG5cbi8qKiBUaW1lIGluIG1zIHRvIHRocm90dGxlIHJlcG9zaXRpb25pbmcgYWZ0ZXIgc2Nyb2xsIGV2ZW50cy4gKi9cbmV4cG9ydCBjb25zdCBTQ1JPTExfVEhST1RUTEVfTVMgPSAyMDtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldEJyblRvb2x0aXBJbnZhbGlkUG9zaXRpb25FcnJvcihwb3NpdGlvbjogc3RyaW5nKSB7XG5cdHJldHVybiBFcnJvcihgVG9vbHRpcCBwb3NpdGlvbiBcIiR7cG9zaXRpb259XCIgaXMgaW52YWxpZC5gKTtcbn1cblxuLyoqIEluamVjdGlvbiB0b2tlbiB0aGF0IGRldGVybWluZXMgdGhlIHNjcm9sbCBoYW5kbGluZyB3aGlsZSBhIHRvb2x0aXAgaXMgdmlzaWJsZS4gKi9cbmV4cG9ydCBjb25zdCBCUk5fVE9PTFRJUF9TQ1JPTExfU1RSQVRFR1kgPSBuZXcgSW5qZWN0aW9uVG9rZW48KCkgPT4gU2Nyb2xsU3RyYXRlZ3k+KCdicm4tdG9vbHRpcC1zY3JvbGwtc3RyYXRlZ3knKTtcbmV4cG9ydCBjb25zdCBCUk5fVE9PTFRJUF9TQ1JPTExfU1RSQVRFR1lfRkFDVE9SWV9QUk9WSURFUjogUHJvdmlkZXIgPSB7XG5cdHByb3ZpZGU6IEJSTl9UT09MVElQX1NDUk9MTF9TVFJBVEVHWSxcblx0ZGVwczogW092ZXJsYXldLFxuXHR1c2VGYWN0b3J5OlxuXHRcdChvdmVybGF5OiBPdmVybGF5KTogKCgpID0+IFNjcm9sbFN0cmF0ZWd5KSA9PlxuXHRcdCgpID0+XG5cdFx0XHRvdmVybGF5LnNjcm9sbFN0cmF0ZWdpZXMucmVwb3NpdGlvbih7IHNjcm9sbFRocm90dGxlOiBTQ1JPTExfVEhST1RUTEVfTVMgfSksXG59O1xuXG5jb25zdCBQQU5FTF9DTEFTUyA9ICd0b29sdGlwLXBhbmVsJztcblxuLyoqIE9wdGlvbnMgdXNlZCB0byBiaW5kIHBhc3NpdmUgZXZlbnQgbGlzdGVuZXJzLiAqL1xuY29uc3QgcGFzc2l2ZUxpc3RlbmVyT3B0aW9ucyA9IG5vcm1hbGl6ZVBhc3NpdmVMaXN0ZW5lck9wdGlvbnMoeyBwYXNzaXZlOiB0cnVlIH0pO1xuXG4vKipcbiAqIFRpbWUgYmV0d2VlbiB0aGUgdXNlciBwdXR0aW5nIHRoZSBwb2ludGVyIG9uIGEgdG9vbHRpcFxuICogdHJpZ2dlciBhbmQgdGhlIGxvbmcgcHJlc3MgZXZlbnQgYmVpbmcgZmlyZWQuXG4gKi9cbmNvbnN0IExPTkdQUkVTU19ERUxBWSA9IDUwMDtcblxuLy8gVGhlc2UgY29uc3RhbnRzIHdlcmUgdGFrZW4gZnJvbSBNREMncyBgbnVtYmVyc2Agb2JqZWN0LlxuY29uc3QgTUlOX1ZJRVdQT1JUX1RPT0xUSVBfVEhSRVNIT0xEID0gODtcbmNvbnN0IFVOQk9VTkRFRF9BTkNIT1JfR0FQID0gODtcblxuQERpcmVjdGl2ZSh7XG5cdHNlbGVjdG9yOiAnW2JyblRvb2x0aXBUcmlnZ2VyXScsXG5cdHN0YW5kYWxvbmU6IHRydWUsXG5cdGV4cG9ydEFzOiAnYnJuVG9vbHRpcFRyaWdnZXInLFxuXHRwcm92aWRlcnM6IFtCUk5fVE9PTFRJUF9TQ1JPTExfU1RSQVRFR1lfRkFDVE9SWV9QUk9WSURFUl0sXG5cdGhvc3Q6IHtcblx0XHRjbGFzczogJ2Jybi10b29sdGlwLXRyaWdnZXInLFxuXHRcdCdbY2xhc3MuYnJuLXRvb2x0aXAtZGlzYWJsZWRdJzogJ2JyblRvb2x0aXBEaXNhYmxlZCgpJyxcblx0fSxcbn0pXG5leHBvcnQgY2xhc3MgQnJuVG9vbHRpcFRyaWdnZXJEaXJlY3RpdmUgaW1wbGVtZW50cyBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQge1xuXHRwcml2YXRlIHJlYWRvbmx5IF90b29sdGlwRGlyZWN0aXZlID0gaW5qZWN0KEJyblRvb2x0aXBEaXJlY3RpdmUsIHsgb3B0aW9uYWw6IHRydWUgfSk7XG5cdHByaXZhdGUgcmVhZG9ubHkgX3Rvb2x0aXBDb21wb25lbnQgPSBCcm5Ub29sdGlwQ29udGVudENvbXBvbmVudDtcblx0cHJpdmF0ZSByZWFkb25seSBfY3NzQ2xhc3NQcmVmaXg6IHN0cmluZyA9ICdicm4nO1xuXHRwcml2YXRlIHJlYWRvbmx5IF9kZXN0cm95ZWQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXHRwcml2YXRlIHJlYWRvbmx5IF9wYXNzaXZlTGlzdGVuZXJzOiAocmVhZG9ubHkgW3N0cmluZywgRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdF0pW10gPSBbXTtcblx0cHJpdmF0ZSByZWFkb25seSBfZGVmYXVsdE9wdGlvbnMgPSBpbmplY3RCcm5Ub29sdGlwRGVmYXVsdE9wdGlvbnMoKTtcblxuXHRwcml2YXRlIHJlYWRvbmx5IF9vdmVybGF5ID0gaW5qZWN0KE92ZXJsYXkpO1xuXHRwcml2YXRlIHJlYWRvbmx5IF9lbGVtZW50UmVmID0gaW5qZWN0KEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+KTtcblx0cHJpdmF0ZSByZWFkb25seSBfc2Nyb2xsRGlzcGF0Y2hlciA9IGluamVjdChTY3JvbGxEaXNwYXRjaGVyKTtcblx0cHJpdmF0ZSByZWFkb25seSBfdmlld0NvbnRhaW5lclJlZiA9IGluamVjdChWaWV3Q29udGFpbmVyUmVmKTtcblx0cHJpdmF0ZSByZWFkb25seSBfbmdab25lID0gaW5qZWN0KE5nWm9uZSk7XG5cdHByaXZhdGUgcmVhZG9ubHkgX3BsYXRmb3JtID0gaW5qZWN0KFBsYXRmb3JtKTtcblx0cHJpdmF0ZSByZWFkb25seSBfYXJpYURlc2NyaWJlciA9IGluamVjdChBcmlhRGVzY3JpYmVyKTtcblx0cHJpdmF0ZSByZWFkb25seSBfZm9jdXNNb25pdG9yID0gaW5qZWN0KEZvY3VzTW9uaXRvcik7XG5cdHByaXZhdGUgcmVhZG9ubHkgX2RpciA9IGluamVjdChEaXJlY3Rpb25hbGl0eSk7XG5cdHByaXZhdGUgcmVhZG9ubHkgX3Njcm9sbFN0cmF0ZWd5ID0gaW5qZWN0KEJSTl9UT09MVElQX1NDUk9MTF9TVFJBVEVHWSk7XG5cdHByaXZhdGUgcmVhZG9ubHkgX2RvY3VtZW50ID0gaW5qZWN0KERPQ1VNRU5UKTtcblxuXHRwcml2YXRlIF9wb3J0YWw/OiBDb21wb25lbnRQb3J0YWw8QnJuVG9vbHRpcENvbnRlbnRDb21wb25lbnQ+O1xuXHRwcml2YXRlIF92aWV3SW5pdGlhbGl6ZWQgPSBmYWxzZTtcblx0cHJpdmF0ZSBfcG9pbnRlckV4aXRFdmVudHNJbml0aWFsaXplZCA9IGZhbHNlO1xuXHRwcml2YXRlIHJlYWRvbmx5IF92aWV3cG9ydE1hcmdpbiA9IDg7XG5cdHByaXZhdGUgX2N1cnJlbnRQb3NpdGlvbj86IFRvb2x0aXBQb3NpdGlvbjtcblx0cHJpdmF0ZSBfdG91Y2hzdGFydFRpbWVvdXQ/OiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PjtcblxuXHRwcml2YXRlIF9vdmVybGF5UmVmOiBPdmVybGF5UmVmIHwgbnVsbCA9IG51bGw7XG5cdHByaXZhdGUgX3Rvb2x0aXBJbnN0YW5jZTogQnJuVG9vbHRpcENvbnRlbnRDb21wb25lbnQgfCBudWxsID0gbnVsbDtcblxuXHQvKiogQWxsb3dzIHRoZSB1c2VyIHRvIGRlZmluZSB0aGUgcG9zaXRpb24gb2YgdGhlIHRvb2x0aXAgcmVsYXRpdmUgdG8gdGhlIHBhcmVudCBlbGVtZW50ICovXG5cblx0cHVibGljIHJlYWRvbmx5IHBvc2l0aW9uID0gaW5wdXQ8VG9vbHRpcFBvc2l0aW9uPih0aGlzLl9kZWZhdWx0T3B0aW9ucz8ucG9zaXRpb24gPz8gJ2Fib3ZlJyk7XG5cblx0LyoqXG5cdCAqIFdoZXRoZXIgdG9vbHRpcCBzaG91bGQgYmUgcmVsYXRpdmUgdG8gdGhlIGNsaWNrIG9yIHRvdWNoIG9yaWdpblxuXHQgKiBpbnN0ZWFkIG9mIG91dHNpZGUgdGhlIGVsZW1lbnQgYm91bmRpbmcgYm94LlxuXHQgKi9cblxuXHRwdWJsaWMgcmVhZG9ubHkgcG9zaXRpb25BdE9yaWdpbiA9IGlucHV0KHRoaXMuX2RlZmF1bHRPcHRpb25zPy5wb3NpdGlvbkF0T3JpZ2luID8/IGZhbHNlLCB7XG5cdFx0dHJhbnNmb3JtOiBib29sZWFuQXR0cmlidXRlLFxuXHR9KTtcblxuXHQvKiogRGlzYWJsZXMgdGhlIGRpc3BsYXkgb2YgdGhlIHRvb2x0aXAuICovXG5cblx0cHVibGljIHJlYWRvbmx5IGJyblRvb2x0aXBEaXNhYmxlZCA9IGlucHV0KGZhbHNlLCB7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KTtcblxuXHQvKiogVGhlIGRlZmF1bHQgZGVsYXkgaW4gbXMgYmVmb3JlIHNob3dpbmcgdGhlIHRvb2x0aXAgYWZ0ZXIgc2hvdyBpcyBjYWxsZWQgKi9cblxuXHRwdWJsaWMgcmVhZG9ubHkgc2hvd0RlbGF5ID0gaW5wdXQodGhpcy5fZGVmYXVsdE9wdGlvbnM/LnNob3dEZWxheSA/PyAwLCB7IHRyYW5zZm9ybTogbnVtYmVyQXR0cmlidXRlIH0pO1xuXG5cdC8qKiBUaGUgZGVmYXVsdCBkZWxheSBpbiBtcyBiZWZvcmUgaGlkaW5nIHRoZSB0b29sdGlwIGFmdGVyIGhpZGUgaXMgY2FsbGVkICovXG5cblx0cHVibGljIHJlYWRvbmx5IGhpZGVEZWxheSA9IGlucHV0KHRoaXMuX2RlZmF1bHRPcHRpb25zPy5oaWRlRGVsYXkgPz8gMCwgeyB0cmFuc2Zvcm06IG51bWJlckF0dHJpYnV0ZSB9KTtcblxuXHQvKiogVGhlIGRlZmF1bHQgZHVyYXRpb24gaW4gbXMgdGhhdCBleGl0IGFuaW1hdGlvbiB0YWtlcyBiZWZvcmUgaGlkaW5nICovXG5cblx0cHVibGljIHJlYWRvbmx5IGV4aXRBbmltYXRpb25EdXJhdGlvbiA9IGlucHV0KHRoaXMuX2RlZmF1bHRPcHRpb25zPy5leGl0QW5pbWF0aW9uRHVyYXRpb24gPz8gMCwge1xuXHRcdHRyYW5zZm9ybTogbnVtYmVyQXR0cmlidXRlLFxuXHR9KTtcblxuXHQvKiogVGhlIGRlZmF1bHQgZGVsYXkgaW4gbXMgYmVmb3JlIGhpZGluZyB0aGUgdG9vbHRpcCBhZnRlciBoaWRlIGlzIGNhbGxlZCAqL1xuXG5cdHB1YmxpYyByZWFkb25seSB0b29sdGlwQ29udGVudENsYXNzZXMgPSBpbnB1dDxzdHJpbmc+KHRoaXMuX2RlZmF1bHRPcHRpb25zPy50b29sdGlwQ29udGVudENsYXNzZXMgPz8gJycpO1xuXG5cdC8qKlxuXHQgKiBIb3cgdG91Y2ggZ2VzdHVyZXMgc2hvdWxkIGJlIGhhbmRsZWQgYnkgdGhlIHRvb2x0aXAuIE9uIHRvdWNoIGRldmljZXMgdGhlIHRvb2x0aXAgZGlyZWN0aXZlXG5cdCAqIHVzZXMgYSBsb25nIHByZXNzIGdlc3R1cmUgdG8gc2hvdyBhbmQgaGlkZSwgaG93ZXZlciBpdCBjYW4gY29uZmxpY3Qgd2l0aCB0aGUgbmF0aXZlIGJyb3dzZXJcblx0ICogZ2VzdHVyZXMuIFRvIHdvcmsgYXJvdW5kIHRoZSBjb25mbGljdCwgQW5ndWxhciBNYXRlcmlhbCBkaXNhYmxlcyBuYXRpdmUgZ2VzdHVyZXMgb24gdGhlXG5cdCAqIHRyaWdnZXIsIGJ1dCB0aGF0IG1pZ2h0IG5vdCBiZSBkZXNpcmFibGUgb24gcGFydGljdWxhciBlbGVtZW50cyAoZS5nLiBpbnB1dHMgYW5kIGRyYWdnYWJsZVxuXHQgKiBlbGVtZW50cykuIFRoZSBkaWZmZXJlbnQgdmFsdWVzIGZvciB0aGlzIG9wdGlvbiBjb25maWd1cmUgdGhlIHRvdWNoIGV2ZW50IGhhbmRsaW5nIGFzIGZvbGxvd3M6XG5cdCAqIC0gYGF1dG9gIC0gRW5hYmxlcyB0b3VjaCBnZXN0dXJlcyBmb3IgYWxsIGVsZW1lbnRzLCBidXQgdHJpZXMgdG8gYXZvaWQgY29uZmxpY3RzIHdpdGggbmF0aXZlXG5cdCAqICAgYnJvd3NlciBnZXN0dXJlcyBvbiBwYXJ0aWN1bGFyIGVsZW1lbnRzLiBJbiBwYXJ0aWN1bGFyLCBpdCBhbGxvd3MgdGV4dCBzZWxlY3Rpb24gb24gaW5wdXRzXG5cdCAqICAgYW5kIHRleHRhcmVhcywgYW5kIHByZXNlcnZlcyB0aGUgbmF0aXZlIGJyb3dzZXIgZHJhZ2dpbmcgb24gZWxlbWVudHMgbWFya2VkIGFzIGBkcmFnZ2FibGVgLlxuXHQgKiAtIGBvbmAgLSBFbmFibGVzIHRvdWNoIGdlc3R1cmVzIGZvciBhbGwgZWxlbWVudHMgYW5kIGRpc2FibGVzIG5hdGl2ZVxuXHQgKiAgIGJyb3dzZXIgZ2VzdHVyZXMgd2l0aCBubyBleGNlcHRpb25zLlxuXHQgKiAtIGBvZmZgIC0gRGlzYWJsZXMgdG91Y2ggZ2VzdHVyZXMuIE5vdGUgdGhhdCB0aGlzIHdpbGwgcHJldmVudCB0aGUgdG9vbHRpcCBmcm9tXG5cdCAqICAgc2hvd2luZyBvbiB0b3VjaCBkZXZpY2VzLlxuXHQgKi9cblxuXHRwdWJsaWMgcmVhZG9ubHkgdG91Y2hHZXN0dXJlcyA9IGlucHV0PFRvb2x0aXBUb3VjaEdlc3R1cmVzPih0aGlzLl9kZWZhdWx0T3B0aW9ucz8udG91Y2hHZXN0dXJlcyA/PyAnYXV0bycpO1xuXG5cdC8qKiBUaGUgbWVzc2FnZSB0byBiZSB1c2VkIHRvIGRlc2NyaWJlIHRoZSBhcmlhIGluIHRoZSB0b29sdGlwICovXG5cblx0cHVibGljIHJlYWRvbmx5IGFyaWFEZXNjcmliZWRCeSA9IGlucHV0KCcnLCB7IGFsaWFzOiAnYXJpYS1kZXNjcmliZWRieScgfSk7XG5cdHB1YmxpYyByZWFkb25seSBhcmlhRGVzY3JpYmVkQnlQcmV2aW91cyA9IGNvbXB1dGVkUHJldmlvdXModGhpcy5hcmlhRGVzY3JpYmVkQnkpO1xuXG5cdC8qKiBUaGUgY29udGVudCB0byBiZSBkaXNwbGF5ZWQgaW4gdGhlIHRvb2x0aXAgKi9cblxuXHRwdWJsaWMgcmVhZG9ubHkgYnJuVG9vbHRpcFRyaWdnZXIgPSBpbnB1dDxzdHJpbmcgfCBUZW1wbGF0ZVJlZjx1bmtub3duPiB8IG51bGw+KG51bGwpO1xuXHRwdWJsaWMgcmVhZG9ubHkgYnJuVG9vbHRpcFRyaWdnZXJTdGF0ZSA9IGNvbXB1dGVkKCgpID0+IHtcblx0XHRpZiAodGhpcy5fdG9vbHRpcERpcmVjdGl2ZSkge1xuXHRcdFx0cmV0dXJuIHRoaXMuX3Rvb2x0aXBEaXJlY3RpdmUudG9vbHRpcFRlbXBsYXRlKCk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzLmJyblRvb2x0aXBUcmlnZ2VyKCk7XG5cdH0pO1xuXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdHRoaXMuX2Rpci5jaGFuZ2UucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveWVkKSkuc3Vic2NyaWJlKCgpID0+IHtcblx0XHRcdGlmICh0aGlzLl9vdmVybGF5UmVmKSB7XG5cdFx0XHRcdHRoaXMuX3VwZGF0ZVBvc2l0aW9uKHRoaXMuX292ZXJsYXlSZWYpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0dGhpcy5fdmlld3BvcnRNYXJnaW4gPSBNSU5fVklFV1BPUlRfVE9PTFRJUF9USFJFU0hPTEQ7XG5cblx0XHR0aGlzLl9pbml0QnJuVG9vbHRpcFRyaWdnZXJFZmZlY3QoKTtcblx0XHR0aGlzLl9pbml0QXJpYURlc2NyaWJlZEJ5UHJldmlvdXNFZmZlY3QoKTtcblx0XHR0aGlzLl9pbml0VG9vbHRpcENvbnRlbnRDbGFzc2VzRWZmZWN0KCk7XG5cdFx0dGhpcy5faW5pdFBvc2l0aW9uRWZmZWN0KCk7XG5cdFx0dGhpcy5faW5pdFBvc2l0aW9uQXRPcmlnaW5FZmZlY3QoKTtcblx0XHR0aGlzLl9pbml0QnJuVG9vbHRpcERpc2FibGVkRWZmZWN0KCk7XG5cdFx0dGhpcy5faW5pdEV4aXRBbmltYXRpb25EdXJhdGlvbkVmZmVjdCgpO1xuXHRcdHRoaXMuX2luaXRIaWRlRGVsYXlFZmZlY3QoKTtcblx0fVxuXG5cdHByaXZhdGUgX2luaXRQb3NpdGlvbkVmZmVjdCgpOiB2b2lkIHtcblx0XHRlZmZlY3QoKCkgPT4ge1xuXHRcdFx0aWYgKHRoaXMuX292ZXJsYXlSZWYpIHtcblx0XHRcdFx0dGhpcy5fdXBkYXRlUG9zaXRpb24odGhpcy5fb3ZlcmxheVJlZik7XG5cdFx0XHRcdHRoaXMuX3Rvb2x0aXBJbnN0YW5jZT8uc2hvdygwKTtcblx0XHRcdFx0dGhpcy5fb3ZlcmxheVJlZi51cGRhdGVQb3NpdGlvbigpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0cHJpdmF0ZSBfaW5pdEJyblRvb2x0aXBEaXNhYmxlZEVmZmVjdCgpOiB2b2lkIHtcblx0XHRlZmZlY3QoKCkgPT4ge1xuXHRcdFx0aWYgKHRoaXMuYnJuVG9vbHRpcERpc2FibGVkKCkpIHtcblx0XHRcdFx0dGhpcy5oaWRlKDApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5fc2V0dXBQb2ludGVyRW50ZXJFdmVudHNJZk5lZWRlZCgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0cHJpdmF0ZSBfaW5pdFBvc2l0aW9uQXRPcmlnaW5FZmZlY3QoKTogdm9pZCB7XG5cdFx0ZWZmZWN0KCgpID0+IHtcblx0XHRcdC8vIE5lZWRlZCB0aGF0IHRoZSBlZmZlY3QgZ290IHRyaWdnZXJlZFxuXHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuXHRcdFx0Y29uc3QgXyA9IHRoaXMucG9zaXRpb25BdE9yaWdpbigpO1xuXHRcdFx0dGhpcy5fZGV0YWNoKCk7XG5cdFx0XHR0aGlzLl9vdmVybGF5UmVmID0gbnVsbDtcblx0XHR9KTtcblx0fVxuXG5cdHByaXZhdGUgX2luaXRUb29sdGlwQ29udGVudENsYXNzZXNFZmZlY3QoKTogdm9pZCB7XG5cdFx0ZWZmZWN0KCgpID0+IHtcblx0XHRcdGlmICh0aGlzLl90b29sdGlwSW5zdGFuY2UpIHtcblx0XHRcdFx0dGhpcy5fdG9vbHRpcEluc3RhbmNlLl90b29sdGlwQ2xhc3Nlcy5zZXQodGhpcy50b29sdGlwQ29udGVudENsYXNzZXMoKSA/PyAnJyk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdH1cblxuXHRwcml2YXRlIF9pbml0QXJpYURlc2NyaWJlZEJ5UHJldmlvdXNFZmZlY3QoKTogdm9pZCB7XG5cdFx0ZWZmZWN0KCgpID0+IHtcblx0XHRcdGNvbnN0IGFyaWFEZXNjcmliZWRCeSA9IHRoaXMuYXJpYURlc2NyaWJlZEJ5KCk7XG5cdFx0XHR0aGlzLl9hcmlhRGVzY3JpYmVyLnJlbW92ZURlc2NyaXB0aW9uKFxuXHRcdFx0XHR0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsXG5cdFx0XHRcdHVudHJhY2tlZCgoKSA9PiB0aGlzLmFyaWFEZXNjcmliZWRCeVByZXZpb3VzKCkpLFxuXHRcdFx0XHQndG9vbHRpcCcsXG5cdFx0XHQpO1xuXG5cdFx0XHRpZiAoYXJpYURlc2NyaWJlZEJ5ICYmICF0aGlzLl9pc1Rvb2x0aXBWaXNpYmxlKCkpIHtcblx0XHRcdFx0dGhpcy5fbmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcblx0XHRcdFx0XHQvLyBUaGUgYEFyaWFEZXNjcmliZXJgIGhhcyBzb21lIGZ1bmN0aW9uYWxpdHkgdGhhdCBhdm9pZHMgYWRkaW5nIGEgZGVzY3JpcHRpb24gaWYgaXQncyB0aGVcblx0XHRcdFx0XHQvLyBzYW1lIGFzIHRoZSBgYXJpYS1sYWJlbGAgb2YgYW4gZWxlbWVudCwgaG93ZXZlciB3ZSBjYW4ndCBrbm93IHdoZXRoZXIgdGhlIHRvb2x0aXAgdHJpZ2dlclxuXHRcdFx0XHRcdC8vIGhhcyBhIGRhdGEtYm91bmQgYGFyaWEtbGFiZWxgIG9yIHdoZW4gaXQnbGwgYmUgc2V0IGZvciB0aGUgZmlyc3QgdGltZS4gV2UgY2FuIGF2b2lkIHRoZVxuXHRcdFx0XHRcdC8vIGlzc3VlIGJ5IGRlZmVycmluZyB0aGUgZGVzY3JpcHRpb24gYnkgYSB0aWNrIHNvIEFuZ3VsYXIgaGFzIHRpbWUgdG8gc2V0IHRoZSBgYXJpYS1sYWJlbGAuXG5cdFx0XHRcdFx0UHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLl9hcmlhRGVzY3JpYmVyLmRlc2NyaWJlKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgYXJpYURlc2NyaWJlZEJ5LCAndG9vbHRpcCcpO1xuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdHByaXZhdGUgX2luaXRCcm5Ub29sdGlwVHJpZ2dlckVmZmVjdCgpOiB2b2lkIHtcblx0XHRlZmZlY3QoKCkgPT4ge1xuXHRcdFx0Y29uc3QgYnJuVG9vbHRpcFRyaWdnZXJTdGF0ZSA9IHRoaXMuYnJuVG9vbHRpcFRyaWdnZXJTdGF0ZSgpO1xuXHRcdFx0Y29uc3QgaXNUb29sdGlwVmlzaWJsZSA9IHRoaXMuX2lzVG9vbHRpcFZpc2libGUoKTtcblx0XHRcdHVudHJhY2tlZCgoKSA9PiB7XG5cdFx0XHRcdGlmICghYnJuVG9vbHRpcFRyaWdnZXJTdGF0ZSAmJiBpc1Rvb2x0aXBWaXNpYmxlKSB7XG5cdFx0XHRcdFx0dGhpcy5oaWRlKDApO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRoaXMuX3NldHVwUG9pbnRlckVudGVyRXZlbnRzSWZOZWVkZWQoKTtcblx0XHRcdFx0XHR0aGlzLl91cGRhdGVUb29sdGlwQ29udGVudCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9KTtcblx0fVxuXG5cdHByaXZhdGUgX2luaXRFeGl0QW5pbWF0aW9uRHVyYXRpb25FZmZlY3QoKTogdm9pZCB7XG5cdFx0ZWZmZWN0KCgpID0+IHtcblx0XHRcdGlmICh0aGlzLl90b29sdGlwSW5zdGFuY2UpIHtcblx0XHRcdFx0dGhpcy5fdG9vbHRpcEluc3RhbmNlLl9leGl0QW5pbWF0aW9uRHVyYXRpb24gPSB0aGlzLmV4aXRBbmltYXRpb25EdXJhdGlvbigpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0cHJpdmF0ZSBfaW5pdEhpZGVEZWxheUVmZmVjdCgpOiB2b2lkIHtcblx0XHRlZmZlY3QoKCkgPT4ge1xuXHRcdFx0aWYgKHRoaXMuX3Rvb2x0aXBJbnN0YW5jZSkge1xuXHRcdFx0XHR0aGlzLl90b29sdGlwSW5zdGFuY2UuX21vdXNlTGVhdmVIaWRlRGVsYXkgPSB0aGlzLmhpZGVEZWxheSgpO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHR9XG5cblx0bmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuXHRcdC8vIFRoaXMgbmVlZHMgdG8gaGFwcGVuIGFmdGVyIHZpZXcgaW5pdCBzbyB0aGUgaW5pdGlhbCB2YWx1ZXMgZm9yIGFsbCBpbnB1dHMgaGF2ZSBiZWVuIHNldC5cblx0XHR0aGlzLl92aWV3SW5pdGlhbGl6ZWQgPSB0cnVlO1xuXHRcdHRoaXMuX3NldHVwUG9pbnRlckVudGVyRXZlbnRzSWZOZWVkZWQoKTtcblxuXHRcdHRoaXMuX2ZvY3VzTW9uaXRvclxuXHRcdFx0Lm1vbml0b3IodGhpcy5fZWxlbWVudFJlZilcblx0XHRcdC5waXBlKHRha2VVbnRpbCh0aGlzLl9kZXN0cm95ZWQpKVxuXHRcdFx0LnN1YnNjcmliZSgob3JpZ2luKSA9PiB7XG5cdFx0XHRcdC8vIE5vdGUgdGhhdCB0aGUgZm9jdXMgbW9uaXRvciBydW5zIG91dHNpZGUgdGhlIEFuZ3VsYXIgem9uZS5cblx0XHRcdFx0aWYgKCFvcmlnaW4pIHtcblx0XHRcdFx0XHR0aGlzLl9uZ1pvbmUucnVuKCgpID0+IHRoaXMuaGlkZSgwKSk7XG5cdFx0XHRcdH0gZWxzZSBpZiAob3JpZ2luID09PSAna2V5Ym9hcmQnKSB7XG5cdFx0XHRcdFx0dGhpcy5fbmdab25lLnJ1bigoKSA9PiB0aGlzLnNob3coKSk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXG5cdFx0aWYgKGJybkRldk1vZGUgJiYgIXRoaXMuYXJpYURlc2NyaWJlZEJ5KCkpIHtcblx0XHRcdGNvbnNvbGUud2FybignQnJuVG9vbHRpcDogXCJhcmlhLWRlc2NyaWJlZGJ5XCIgYXR0cmlidXRlIGlzIHJlcXVpcmVkIGZvciBhY2Nlc3NpYmlsaXR5Jyk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIERpc3Bvc2UgdGhlIHRvb2x0aXAgd2hlbiBkZXN0cm95ZWQuXG5cdCAqL1xuXHRuZ09uRGVzdHJveSgpOiB2b2lkIHtcblx0XHRjb25zdCBuYXRpdmVFbGVtZW50ID0gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuXG5cdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3RvdWNoc3RhcnRUaW1lb3V0KTtcblxuXHRcdGlmICh0aGlzLl9vdmVybGF5UmVmKSB7XG5cdFx0XHR0aGlzLl9vdmVybGF5UmVmLmRpc3Bvc2UoKTtcblx0XHRcdHRoaXMuX3Rvb2x0aXBJbnN0YW5jZSA9IG51bGw7XG5cdFx0fVxuXG5cdFx0Ly8gQ2xlYW4gdXAgdGhlIGV2ZW50IGxpc3RlbmVycyBzZXQgaW4gdGhlIGNvbnN0cnVjdG9yXG5cdFx0dGhpcy5fcGFzc2l2ZUxpc3RlbmVycy5mb3JFYWNoKChbZXZlbnQsIGxpc3RlbmVyXSkgPT5cblx0XHRcdG5hdGl2ZUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudCwgbGlzdGVuZXIsIHBhc3NpdmVMaXN0ZW5lck9wdGlvbnMpLFxuXHRcdCk7XG5cdFx0dGhpcy5fcGFzc2l2ZUxpc3RlbmVycy5sZW5ndGggPSAwO1xuXG5cdFx0dGhpcy5fZGVzdHJveWVkLm5leHQoKTtcblx0XHR0aGlzLl9kZXN0cm95ZWQuY29tcGxldGUoKTtcblxuXHRcdHRoaXMuX2FyaWFEZXNjcmliZXIucmVtb3ZlRGVzY3JpcHRpb24obmF0aXZlRWxlbWVudCwgdGhpcy5hcmlhRGVzY3JpYmVkQnkoKSwgJ3Rvb2x0aXAnKTtcblx0XHR0aGlzLl9mb2N1c01vbml0b3Iuc3RvcE1vbml0b3JpbmcobmF0aXZlRWxlbWVudCk7XG5cdH1cblxuXHQvKiogU2hvd3MgdGhlIHRvb2x0aXAgYWZ0ZXIgdGhlIGRlbGF5IGluIG1zLCBkZWZhdWx0cyB0byB0b29sdGlwLWRlbGF5LXNob3cgb3IgMG1zIGlmIG5vIGlucHV0ICovXG5cdHNob3coZGVsYXk6IG51bWJlciA9IHRoaXMuc2hvd0RlbGF5KCksIG9yaWdpbj86IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSk6IHZvaWQge1xuXHRcdGlmICh0aGlzLmJyblRvb2x0aXBEaXNhYmxlZCgpIHx8IHRoaXMuX2lzVG9vbHRpcFZpc2libGUoKSkge1xuXHRcdFx0dGhpcy5fdG9vbHRpcEluc3RhbmNlPy5fY2FuY2VsUGVuZGluZ0FuaW1hdGlvbnMoKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRjb25zdCBvdmVybGF5UmVmID0gdGhpcy5fY3JlYXRlT3ZlcmxheShvcmlnaW4pO1xuXHRcdHRoaXMuX2RldGFjaCgpO1xuXHRcdHRoaXMuX3BvcnRhbCA9IHRoaXMuX3BvcnRhbCB8fCBuZXcgQ29tcG9uZW50UG9ydGFsKHRoaXMuX3Rvb2x0aXBDb21wb25lbnQsIHRoaXMuX3ZpZXdDb250YWluZXJSZWYpO1xuXHRcdGNvbnN0IGluc3RhbmNlID0gKHRoaXMuX3Rvb2x0aXBJbnN0YW5jZSA9IG92ZXJsYXlSZWYuYXR0YWNoKHRoaXMuX3BvcnRhbCkuaW5zdGFuY2UpO1xuXHRcdGluc3RhbmNlLl90cmlnZ2VyRWxlbWVudCA9IHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcblx0XHRpbnN0YW5jZS5fbW91c2VMZWF2ZUhpZGVEZWxheSA9IHRoaXMuaGlkZURlbGF5KCk7XG5cdFx0aW5zdGFuY2UuX3Rvb2x0aXBDbGFzc2VzLnNldCh0aGlzLnRvb2x0aXBDb250ZW50Q2xhc3NlcygpKTtcblx0XHRpbnN0YW5jZS5fZXhpdEFuaW1hdGlvbkR1cmF0aW9uID0gdGhpcy5leGl0QW5pbWF0aW9uRHVyYXRpb24oKTtcblx0XHRpbnN0YW5jZS5zaWRlLnNldCh0aGlzLl9jdXJyZW50UG9zaXRpb24gPz8gJ2Fib3ZlJyk7XG5cdFx0aW5zdGFuY2UuYWZ0ZXJIaWRkZW4ucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveWVkKSkuc3Vic2NyaWJlKCgpID0+IHRoaXMuX2RldGFjaCgpKTtcblx0XHR0aGlzLl91cGRhdGVUb29sdGlwQ29udGVudCgpO1xuXHRcdGluc3RhbmNlLnNob3coZGVsYXkpO1xuXHR9XG5cblx0LyoqIEhpZGVzIHRoZSB0b29sdGlwIGFmdGVyIHRoZSBkZWxheSBpbiBtcywgZGVmYXVsdHMgdG8gdG9vbHRpcC1kZWxheS1oaWRlIG9yIDBtcyBpZiBubyBpbnB1dCAqL1xuXHRoaWRlKGRlbGF5OiBudW1iZXIgPSB0aGlzLmhpZGVEZWxheSgpLCBleGl0QW5pbWF0aW9uRHVyYXRpb246IG51bWJlciA9IHRoaXMuZXhpdEFuaW1hdGlvbkR1cmF0aW9uKCkpOiB2b2lkIHtcblx0XHRjb25zdCBpbnN0YW5jZSA9IHRoaXMuX3Rvb2x0aXBJbnN0YW5jZTtcblx0XHRpZiAoaW5zdGFuY2UpIHtcblx0XHRcdGlmIChpbnN0YW5jZS5pc1Zpc2libGUoKSkge1xuXHRcdFx0XHRpbnN0YW5jZS5oaWRlKGRlbGF5LCBleGl0QW5pbWF0aW9uRHVyYXRpb24pO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aW5zdGFuY2UuX2NhbmNlbFBlbmRpbmdBbmltYXRpb25zKCk7XG5cdFx0XHRcdHRoaXMuX2RldGFjaCgpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHRvZ2dsZShvcmlnaW4/OiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0pOiB2b2lkIHtcblx0XHR0aGlzLl9pc1Rvb2x0aXBWaXNpYmxlKCkgPyB0aGlzLmhpZGUoKSA6IHRoaXMuc2hvdyh1bmRlZmluZWQsIG9yaWdpbik7XG5cdH1cblxuXHRfaXNUb29sdGlwVmlzaWJsZSgpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gISF0aGlzLl90b29sdGlwSW5zdGFuY2UgJiYgdGhpcy5fdG9vbHRpcEluc3RhbmNlLmlzVmlzaWJsZSgpO1xuXHR9XG5cblx0cHJpdmF0ZSBfY3JlYXRlT3ZlcmxheShvcmlnaW4/OiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0pOiBPdmVybGF5UmVmIHtcblx0XHRpZiAodGhpcy5fb3ZlcmxheVJlZikge1xuXHRcdFx0Y29uc3QgZXhpc3RpbmdTdHJhdGVneSA9IHRoaXMuX292ZXJsYXlSZWYuZ2V0Q29uZmlnKCkucG9zaXRpb25TdHJhdGVneSBhcyBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3k7XG5cblx0XHRcdGlmICgoIXRoaXMucG9zaXRpb25BdE9yaWdpbigpIHx8ICFvcmlnaW4pICYmIGV4aXN0aW5nU3RyYXRlZ3kuX29yaWdpbiBpbnN0YW5jZW9mIEVsZW1lbnRSZWYpIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuX292ZXJsYXlSZWY7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuX2RldGFjaCgpO1xuXHRcdH1cblxuXHRcdGNvbnN0IHNjcm9sbGFibGVBbmNlc3RvcnMgPSB0aGlzLl9zY3JvbGxEaXNwYXRjaGVyLmdldEFuY2VzdG9yU2Nyb2xsQ29udGFpbmVycyh0aGlzLl9lbGVtZW50UmVmKTtcblxuXHRcdC8vIENyZWF0ZSBjb25uZWN0ZWQgcG9zaXRpb24gc3RyYXRlZ3kgdGhhdCBsaXN0ZW5zIGZvciBzY3JvbGwgZXZlbnRzIHRvIHJlcG9zaXRpb24uXG5cdFx0Y29uc3Qgc3RyYXRlZ3kgPSB0aGlzLl9vdmVybGF5XG5cdFx0XHQucG9zaXRpb24oKVxuXHRcdFx0LmZsZXhpYmxlQ29ubmVjdGVkVG8odGhpcy5wb3NpdGlvbkF0T3JpZ2luKCkgPyBvcmlnaW4gfHwgdGhpcy5fZWxlbWVudFJlZiA6IHRoaXMuX2VsZW1lbnRSZWYpXG5cdFx0XHQud2l0aFRyYW5zZm9ybU9yaWdpbk9uKGAuJHt0aGlzLl9jc3NDbGFzc1ByZWZpeH0tdG9vbHRpcGApXG5cdFx0XHQud2l0aEZsZXhpYmxlRGltZW5zaW9ucyhmYWxzZSlcblx0XHRcdC53aXRoVmlld3BvcnRNYXJnaW4odGhpcy5fdmlld3BvcnRNYXJnaW4pXG5cdFx0XHQud2l0aFNjcm9sbGFibGVDb250YWluZXJzKHNjcm9sbGFibGVBbmNlc3RvcnMpO1xuXG5cdFx0c3RyYXRlZ3kucG9zaXRpb25DaGFuZ2VzLnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3llZCkpLnN1YnNjcmliZSgoY2hhbmdlKSA9PiB7XG5cdFx0XHR0aGlzLl91cGRhdGVDdXJyZW50UG9zaXRpb25DbGFzcyhjaGFuZ2UuY29ubmVjdGlvblBhaXIpO1xuXG5cdFx0XHRpZiAodGhpcy5fdG9vbHRpcEluc3RhbmNlKSB7XG5cdFx0XHRcdGlmIChjaGFuZ2Uuc2Nyb2xsYWJsZVZpZXdQcm9wZXJ0aWVzLmlzT3ZlcmxheUNsaXBwZWQgJiYgdGhpcy5fdG9vbHRpcEluc3RhbmNlLmlzVmlzaWJsZSgpKSB7XG5cdFx0XHRcdFx0Ly8gQWZ0ZXIgcG9zaXRpb24gY2hhbmdlcyBvY2N1ciBhbmQgdGhlIG92ZXJsYXkgaXMgY2xpcHBlZCBieVxuXHRcdFx0XHRcdC8vIGEgcGFyZW50IHNjcm9sbGFibGUgdGhlbiBjbG9zZSB0aGUgdG9vbHRpcC5cblx0XHRcdFx0XHR0aGlzLl9uZ1pvbmUucnVuKCgpID0+IHRoaXMuaGlkZSgwKSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdHRoaXMuX292ZXJsYXlSZWYgPSB0aGlzLl9vdmVybGF5LmNyZWF0ZSh7XG5cdFx0XHRkaXJlY3Rpb246IHRoaXMuX2Rpcixcblx0XHRcdHBvc2l0aW9uU3RyYXRlZ3k6IHN0cmF0ZWd5LFxuXHRcdFx0cGFuZWxDbGFzczogYCR7dGhpcy5fY3NzQ2xhc3NQcmVmaXh9LSR7UEFORUxfQ0xBU1N9YCxcblx0XHRcdHNjcm9sbFN0cmF0ZWd5OiB0aGlzLl9zY3JvbGxTdHJhdGVneSgpLFxuXHRcdH0pO1xuXG5cdFx0dGhpcy5fdXBkYXRlUG9zaXRpb24odGhpcy5fb3ZlcmxheVJlZik7XG5cblx0XHR0aGlzLl9vdmVybGF5UmVmXG5cdFx0XHQuZGV0YWNobWVudHMoKVxuXHRcdFx0LnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3llZCkpXG5cdFx0XHQuc3Vic2NyaWJlKCgpID0+IHRoaXMuX2RldGFjaCgpKTtcblxuXHRcdHRoaXMuX292ZXJsYXlSZWZcblx0XHRcdC5vdXRzaWRlUG9pbnRlckV2ZW50cygpXG5cdFx0XHQucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveWVkKSlcblx0XHRcdC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5fdG9vbHRpcEluc3RhbmNlPy5faGFuZGxlQm9keUludGVyYWN0aW9uKCkpO1xuXG5cdFx0dGhpcy5fb3ZlcmxheVJlZlxuXHRcdFx0LmtleWRvd25FdmVudHMoKVxuXHRcdFx0LnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3llZCkpXG5cdFx0XHQuc3Vic2NyaWJlKChldmVudCkgPT4ge1xuXHRcdFx0XHRpZiAodGhpcy5faXNUb29sdGlwVmlzaWJsZSgpICYmIGV2ZW50LmtleSA9PT0gJ0VzY2FwZScgJiYgIWhhc01vZGlmaWVyS2V5KGV2ZW50KSkge1xuXHRcdFx0XHRcdGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHRcdFx0dGhpcy5fbmdab25lLnJ1bigoKSA9PiB0aGlzLmhpZGUoMCkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblxuXHRcdGlmICh0aGlzLl9kZWZhdWx0T3B0aW9ucz8uZGlzYWJsZVRvb2x0aXBJbnRlcmFjdGl2aXR5KSB7XG5cdFx0XHR0aGlzLl9vdmVybGF5UmVmLmFkZFBhbmVsQ2xhc3MoYCR7dGhpcy5fY3NzQ2xhc3NQcmVmaXh9LXRvb2x0aXAtcGFuZWwtbm9uLWludGVyYWN0aXZlYCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuX292ZXJsYXlSZWY7XG5cdH1cblxuXHRwcml2YXRlIF9kZXRhY2goKTogdm9pZCB7XG5cdFx0aWYgKHRoaXMuX292ZXJsYXlSZWY/Lmhhc0F0dGFjaGVkKCkpIHtcblx0XHRcdHRoaXMuX292ZXJsYXlSZWYuZGV0YWNoKCk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fdG9vbHRpcEluc3RhbmNlID0gbnVsbDtcblx0fVxuXG5cdHByaXZhdGUgX3VwZGF0ZVBvc2l0aW9uKG92ZXJsYXlSZWY6IE92ZXJsYXlSZWYpIHtcblx0XHRjb25zdCBwb3NpdGlvbiA9IG92ZXJsYXlSZWYuZ2V0Q29uZmlnKCkucG9zaXRpb25TdHJhdGVneSBhcyBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3k7XG5cdFx0Y29uc3Qgb3JpZ2luID0gdGhpcy5fZ2V0T3JpZ2luKCk7XG5cdFx0Y29uc3Qgb3ZlcmxheSA9IHRoaXMuX2dldE92ZXJsYXlQb3NpdGlvbigpO1xuXG5cdFx0cG9zaXRpb24ud2l0aFBvc2l0aW9ucyhbXG5cdFx0XHR0aGlzLl9hZGRPZmZzZXQoeyAuLi5vcmlnaW4ubWFpbiwgLi4ub3ZlcmxheS5tYWluIH0pLFxuXHRcdFx0dGhpcy5fYWRkT2Zmc2V0KHsgLi4ub3JpZ2luLmZhbGxiYWNrLCAuLi5vdmVybGF5LmZhbGxiYWNrIH0pLFxuXHRcdF0pO1xuXHR9XG5cblx0LyoqIEFkZHMgdGhlIGNvbmZpZ3VyZWQgb2Zmc2V0IHRvIGEgcG9zaXRpb24uIFVzZWQgYXMgYSBob29rIGZvciBjaGlsZCBjbGFzc2VzLiAqL1xuXHRwcm90ZWN0ZWQgX2FkZE9mZnNldChwb3NpdGlvbjogQ29ubmVjdGVkUG9zaXRpb24pOiBDb25uZWN0ZWRQb3NpdGlvbiB7XG5cdFx0Y29uc3Qgb2Zmc2V0ID0gVU5CT1VOREVEX0FOQ0hPUl9HQVA7XG5cdFx0Y29uc3QgaXNMdHIgPSAhdGhpcy5fZGlyIHx8IHRoaXMuX2Rpci52YWx1ZSA9PT0gJ2x0cic7XG5cblx0XHRpZiAocG9zaXRpb24ub3JpZ2luWSA9PT0gJ3RvcCcpIHtcblx0XHRcdHBvc2l0aW9uLm9mZnNldFkgPSAtb2Zmc2V0O1xuXHRcdH0gZWxzZSBpZiAocG9zaXRpb24ub3JpZ2luWSA9PT0gJ2JvdHRvbScpIHtcblx0XHRcdHBvc2l0aW9uLm9mZnNldFkgPSBvZmZzZXQ7XG5cdFx0fSBlbHNlIGlmIChwb3NpdGlvbi5vcmlnaW5YID09PSAnc3RhcnQnKSB7XG5cdFx0XHRwb3NpdGlvbi5vZmZzZXRYID0gaXNMdHIgPyAtb2Zmc2V0IDogb2Zmc2V0O1xuXHRcdH0gZWxzZSBpZiAocG9zaXRpb24ub3JpZ2luWCA9PT0gJ2VuZCcpIHtcblx0XHRcdHBvc2l0aW9uLm9mZnNldFggPSBpc0x0ciA/IG9mZnNldCA6IC1vZmZzZXQ7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHBvc2l0aW9uO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIG9yaWdpbiBwb3NpdGlvbiBhbmQgYSBmYWxsYmFjayBwb3NpdGlvbiBiYXNlZCBvbiB0aGUgdXNlcidzIHBvc2l0aW9uIHByZWZlcmVuY2UuXG5cdCAqIFRoZSBmYWxsYmFjayBwb3NpdGlvbiBpcyB0aGUgaW52ZXJzZSBvZiB0aGUgb3JpZ2luIChlLmcuIGAnYmVsb3cnIC0+ICdhYm92ZSdgKS5cblx0ICovXG5cdF9nZXRPcmlnaW4oKTogeyBtYWluOiBPcmlnaW5Db25uZWN0aW9uUG9zaXRpb247IGZhbGxiYWNrOiBPcmlnaW5Db25uZWN0aW9uUG9zaXRpb24gfSB7XG5cdFx0Y29uc3QgaXNMdHIgPSAhdGhpcy5fZGlyIHx8IHRoaXMuX2Rpci52YWx1ZSA9PT0gJ2x0cic7XG5cdFx0Y29uc3QgcG9zaXRpb24gPSB0aGlzLnBvc2l0aW9uKCk7XG5cdFx0bGV0IG9yaWdpblBvc2l0aW9uOiBPcmlnaW5Db25uZWN0aW9uUG9zaXRpb247XG5cblx0XHRpZiAocG9zaXRpb24gPT09ICdhYm92ZScgfHwgcG9zaXRpb24gPT09ICdiZWxvdycpIHtcblx0XHRcdG9yaWdpblBvc2l0aW9uID0geyBvcmlnaW5YOiAnY2VudGVyJywgb3JpZ2luWTogcG9zaXRpb24gPT09ICdhYm92ZScgPyAndG9wJyA6ICdib3R0b20nIH07XG5cdFx0fSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2JlZm9yZScgfHwgKHBvc2l0aW9uID09PSAnbGVmdCcgJiYgaXNMdHIpIHx8IChwb3NpdGlvbiA9PT0gJ3JpZ2h0JyAmJiAhaXNMdHIpKSB7XG5cdFx0XHRvcmlnaW5Qb3NpdGlvbiA9IHsgb3JpZ2luWDogJ3N0YXJ0Jywgb3JpZ2luWTogJ2NlbnRlcicgfTtcblx0XHR9IGVsc2UgaWYgKHBvc2l0aW9uID09PSAnYWZ0ZXInIHx8IChwb3NpdGlvbiA9PT0gJ3JpZ2h0JyAmJiBpc0x0cikgfHwgKHBvc2l0aW9uID09PSAnbGVmdCcgJiYgIWlzTHRyKSkge1xuXHRcdFx0b3JpZ2luUG9zaXRpb24gPSB7IG9yaWdpblg6ICdlbmQnLCBvcmlnaW5ZOiAnY2VudGVyJyB9O1xuXHRcdH0gZWxzZSBpZiAodHlwZW9mIGlzRGV2TW9kZSgpID09PSAndW5kZWZpbmVkJyB8fCBpc0Rldk1vZGUoKSkge1xuXHRcdFx0dGhyb3cgZ2V0QnJuVG9vbHRpcEludmFsaWRQb3NpdGlvbkVycm9yKHBvc2l0aW9uKTtcblx0XHR9XG5cblx0XHRjb25zdCB7IHgsIHkgfSA9IHRoaXMuX2ludmVydFBvc2l0aW9uKG9yaWdpblBvc2l0aW9uIS5vcmlnaW5YLCBvcmlnaW5Qb3NpdGlvbiEub3JpZ2luWSk7XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0bWFpbjogb3JpZ2luUG9zaXRpb24hLFxuXHRcdFx0ZmFsbGJhY2s6IHsgb3JpZ2luWDogeCwgb3JpZ2luWTogeSB9LFxuXHRcdH07XG5cdH1cblxuXHQvKiogUmV0dXJucyB0aGUgb3ZlcmxheSBwb3NpdGlvbiBhbmQgYSBmYWxsYmFjayBwb3NpdGlvbiBiYXNlZCBvbiB0aGUgdXNlcidzIHByZWZlcmVuY2UgKi9cblx0X2dldE92ZXJsYXlQb3NpdGlvbigpOiB7IG1haW46IE92ZXJsYXlDb25uZWN0aW9uUG9zaXRpb247IGZhbGxiYWNrOiBPdmVybGF5Q29ubmVjdGlvblBvc2l0aW9uIH0ge1xuXHRcdGNvbnN0IGlzTHRyID0gIXRoaXMuX2RpciB8fCB0aGlzLl9kaXIudmFsdWUgPT09ICdsdHInO1xuXHRcdGNvbnN0IHBvc2l0aW9uID0gdGhpcy5wb3NpdGlvbigpO1xuXHRcdGxldCBvdmVybGF5UG9zaXRpb246IE92ZXJsYXlDb25uZWN0aW9uUG9zaXRpb247XG5cblx0XHRpZiAocG9zaXRpb24gPT09ICdhYm92ZScpIHtcblx0XHRcdG92ZXJsYXlQb3NpdGlvbiA9IHsgb3ZlcmxheVg6ICdjZW50ZXInLCBvdmVybGF5WTogJ2JvdHRvbScgfTtcblx0XHR9IGVsc2UgaWYgKHBvc2l0aW9uID09PSAnYmVsb3cnKSB7XG5cdFx0XHRvdmVybGF5UG9zaXRpb24gPSB7IG92ZXJsYXlYOiAnY2VudGVyJywgb3ZlcmxheVk6ICd0b3AnIH07XG5cdFx0fSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2JlZm9yZScgfHwgKHBvc2l0aW9uID09PSAnbGVmdCcgJiYgaXNMdHIpIHx8IChwb3NpdGlvbiA9PT0gJ3JpZ2h0JyAmJiAhaXNMdHIpKSB7XG5cdFx0XHRvdmVybGF5UG9zaXRpb24gPSB7IG92ZXJsYXlYOiAnZW5kJywgb3ZlcmxheVk6ICdjZW50ZXInIH07XG5cdFx0fSBlbHNlIGlmIChwb3NpdGlvbiA9PT0gJ2FmdGVyJyB8fCAocG9zaXRpb24gPT09ICdyaWdodCcgJiYgaXNMdHIpIHx8IChwb3NpdGlvbiA9PT0gJ2xlZnQnICYmICFpc0x0cikpIHtcblx0XHRcdG92ZXJsYXlQb3NpdGlvbiA9IHsgb3ZlcmxheVg6ICdzdGFydCcsIG92ZXJsYXlZOiAnY2VudGVyJyB9O1xuXHRcdH0gZWxzZSBpZiAodHlwZW9mIGlzRGV2TW9kZSgpID09PSAndW5kZWZpbmVkJyB8fCBpc0Rldk1vZGUoKSkge1xuXHRcdFx0dGhyb3cgZ2V0QnJuVG9vbHRpcEludmFsaWRQb3NpdGlvbkVycm9yKHBvc2l0aW9uKTtcblx0XHR9XG5cblx0XHRjb25zdCB7IHgsIHkgfSA9IHRoaXMuX2ludmVydFBvc2l0aW9uKG92ZXJsYXlQb3NpdGlvbiEub3ZlcmxheVgsIG92ZXJsYXlQb3NpdGlvbiEub3ZlcmxheVkpO1xuXG5cdFx0cmV0dXJuIHtcblx0XHRcdG1haW46IG92ZXJsYXlQb3NpdGlvbiEsXG5cdFx0XHRmYWxsYmFjazogeyBvdmVybGF5WDogeCwgb3ZlcmxheVk6IHkgfSxcblx0XHR9O1xuXHR9XG5cblx0LyoqIFVwZGF0ZXMgdGhlIHRvb2x0aXAgbWVzc2FnZSBhbmQgcmVwb3NpdGlvbnMgdGhlIG92ZXJsYXkgYWNjb3JkaW5nIHRvIHRoZSBuZXcgbWVzc2FnZSBsZW5ndGggKi9cblx0cHJpdmF0ZSBfdXBkYXRlVG9vbHRpcENvbnRlbnQoKTogdm9pZCB7XG5cdFx0Ly8gTXVzdCB3YWl0IGZvciB0aGUgdGVtcGxhdGUgdG8gYmUgcGFpbnRlZCB0byB0aGUgdG9vbHRpcCBzbyB0aGF0IHRoZSBvdmVybGF5IGNhbiBwcm9wZXJseVxuXHRcdC8vIGNhbGN1bGF0ZSB0aGUgY29ycmVjdCBwb3NpdGlvbmluZyBiYXNlZCBvbiB0aGUgc2l6ZSBvZiB0aGUgdGVrLXBhdGUuXG5cdFx0aWYgKHRoaXMuX3Rvb2x0aXBJbnN0YW5jZSkge1xuXHRcdFx0dGhpcy5fdG9vbHRpcEluc3RhbmNlLmNvbnRlbnQgPSB0aGlzLmJyblRvb2x0aXBUcmlnZ2VyU3RhdGUoKTtcblx0XHRcdHRoaXMuX3Rvb2x0aXBJbnN0YW5jZS5fbWFya0ZvckNoZWNrKCk7XG5cblx0XHRcdHRoaXMuX25nWm9uZS5vbk1pY3JvdGFza0VtcHR5LnBpcGUodGFrZSgxKSwgdGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3llZCkpLnN1YnNjcmliZSgoKSA9PiB7XG5cdFx0XHRcdGlmICh0aGlzLl90b29sdGlwSW5zdGFuY2UpIHtcblx0XHRcdFx0XHR0aGlzLl9vdmVybGF5UmVmPy51cGRhdGVQb3NpdGlvbigpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cblxuXHQvKiogSW52ZXJ0cyBhbiBvdmVybGF5IHBvc2l0aW9uLiAqL1xuXHRwcml2YXRlIF9pbnZlcnRQb3NpdGlvbih4OiBIb3Jpem9udGFsQ29ubmVjdGlvblBvcywgeTogVmVydGljYWxDb25uZWN0aW9uUG9zKSB7XG5cdFx0aWYgKHRoaXMucG9zaXRpb24oKSA9PT0gJ2Fib3ZlJyB8fCB0aGlzLnBvc2l0aW9uKCkgPT09ICdiZWxvdycpIHtcblx0XHRcdGlmICh5ID09PSAndG9wJykge1xuXHRcdFx0XHR5ID0gJ2JvdHRvbSc7XG5cdFx0XHR9IGVsc2UgaWYgKHkgPT09ICdib3R0b20nKSB7XG5cdFx0XHRcdHkgPSAndG9wJztcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKHggPT09ICdlbmQnKSB7XG5cdFx0XHRcdHggPSAnc3RhcnQnO1xuXHRcdFx0fSBlbHNlIGlmICh4ID09PSAnc3RhcnQnKSB7XG5cdFx0XHRcdHggPSAnZW5kJztcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4geyB4LCB5IH07XG5cdH1cblxuXHQvKiogVXBkYXRlcyB0aGUgY2xhc3Mgb24gdGhlIG92ZXJsYXkgcGFuZWwgYmFzZWQgb24gdGhlIGN1cnJlbnQgcG9zaXRpb24gb2YgdGhlIHRvb2x0aXAuICovXG5cdHByaXZhdGUgX3VwZGF0ZUN1cnJlbnRQb3NpdGlvbkNsYXNzKGNvbm5lY3Rpb25QYWlyOiBDb25uZWN0aW9uUG9zaXRpb25QYWlyKTogdm9pZCB7XG5cdFx0Y29uc3QgeyBvdmVybGF5WSwgb3JpZ2luWCwgb3JpZ2luWSB9ID0gY29ubmVjdGlvblBhaXI7XG5cdFx0bGV0IG5ld1Bvc2l0aW9uOiBUb29sdGlwUG9zaXRpb247XG5cblx0XHQvLyBJZiB0aGUgb3ZlcmxheSBpcyBpbiB0aGUgbWlkZGxlIGFsb25nIHRoZSBZIGF4aXMsXG5cdFx0Ly8gaXQgbWVhbnMgdGhhdCBpdCdzIGVpdGhlciBiZWZvcmUgb3IgYWZ0ZXIuXG5cdFx0aWYgKG92ZXJsYXlZID09PSAnY2VudGVyJykge1xuXHRcdFx0Ly8gTm90ZSB0aGF0IHNpbmNlIHRoaXMgaW5mb3JtYXRpb24gaXMgdXNlZCBmb3Igc3R5bGluZywgd2Ugd2FudCB0b1xuXHRcdFx0Ly8gcmVzb2x2ZSBgc3RhcnRgIGFuZCBgZW5kYCB0byB0aGVpciByZWFsIHZhbHVlcywgb3RoZXJ3aXNlIGNvbnN1bWVyc1xuXHRcdFx0Ly8gd291bGQgaGF2ZSB0byByZW1lbWJlciB0byBkbyBpdCB0aGVtc2VsdmVzIG9uIGVhY2ggY29uc3VtcHRpb24uXG5cdFx0XHRpZiAodGhpcy5fZGlyICYmIHRoaXMuX2Rpci52YWx1ZSA9PT0gJ3J0bCcpIHtcblx0XHRcdFx0bmV3UG9zaXRpb24gPSBvcmlnaW5YID09PSAnZW5kJyA/ICdsZWZ0JyA6ICdyaWdodCc7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRuZXdQb3NpdGlvbiA9IG9yaWdpblggPT09ICdzdGFydCcgPyAnbGVmdCcgOiAncmlnaHQnO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRuZXdQb3NpdGlvbiA9IG92ZXJsYXlZID09PSAnYm90dG9tJyAmJiBvcmlnaW5ZID09PSAndG9wJyA/ICdhYm92ZScgOiAnYmVsb3cnO1xuXHRcdH1cblxuXHRcdGlmIChuZXdQb3NpdGlvbiAhPT0gdGhpcy5fY3VycmVudFBvc2l0aW9uKSB7XG5cdFx0XHR0aGlzLl90b29sdGlwSW5zdGFuY2U/LnNpZGUuc2V0KG5ld1Bvc2l0aW9uKTtcblx0XHRcdHRoaXMuX2N1cnJlbnRQb3NpdGlvbiA9IG5ld1Bvc2l0aW9uO1xuXHRcdH1cblx0fVxuXG5cdC8qKiBCaW5kcyB0aGUgcG9pbnRlciBldmVudHMgdG8gdGhlIHRvb2x0aXAgdHJpZ2dlci4gKi9cblx0cHJpdmF0ZSBfc2V0dXBQb2ludGVyRW50ZXJFdmVudHNJZk5lZWRlZCgpOiB2b2lkIHtcblx0XHQvLyBPcHRpbWl6YXRpb246IERlZmVyIGhvb2tpbmcgdXAgZXZlbnRzIGlmIHRoZXJlJ3Mgbm8gY29udGVudCBvciB0aGUgdG9vbHRpcCBpcyBkaXNhYmxlZC5cblx0XHRpZiAoXG5cdFx0XHR0aGlzLmJyblRvb2x0aXBEaXNhYmxlZCgpIHx8XG5cdFx0XHQhdGhpcy5icm5Ub29sdGlwVHJpZ2dlclN0YXRlKCkgfHxcblx0XHRcdCF0aGlzLl92aWV3SW5pdGlhbGl6ZWQgfHxcblx0XHRcdHRoaXMuX3Bhc3NpdmVMaXN0ZW5lcnMubGVuZ3RoXG5cdFx0KSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gVGhlIG1vdXNlIGV2ZW50cyBzaG91bGRuJ3QgYmUgYm91bmQgb24gbW9iaWxlIGRldmljZXMsIGJlY2F1c2UgdGhleSBjYW4gcHJldmVudCB0aGVcblx0XHQvLyBmaXJzdCB0YXAgZnJvbSBmaXJpbmcgaXRzIGNsaWNrIGV2ZW50IG9yIGNhbiBjYXVzZSB0aGUgdG9vbHRpcCB0byBvcGVuIGZvciBjbGlja3MuXG5cdFx0aWYgKHRoaXMuX3BsYXRmb3JtU3VwcG9ydHNNb3VzZUV2ZW50cygpKSB7XG5cdFx0XHR0aGlzLl9wYXNzaXZlTGlzdGVuZXJzLnB1c2goW1xuXHRcdFx0XHQnbW91c2VlbnRlcicsXG5cdFx0XHRcdChldmVudCkgPT4ge1xuXHRcdFx0XHRcdHRoaXMuX3NldHVwUG9pbnRlckV4aXRFdmVudHNJZk5lZWRlZCgpO1xuXHRcdFx0XHRcdGxldCBwb2ludCA9IHVuZGVmaW5lZDtcblx0XHRcdFx0XHRpZiAoKGV2ZW50IGFzIE1vdXNlRXZlbnQpLnggIT09IHVuZGVmaW5lZCAmJiAoZXZlbnQgYXMgTW91c2VFdmVudCkueSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0XHRwb2ludCA9IGV2ZW50IGFzIE1vdXNlRXZlbnQ7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHRoaXMuc2hvdyh1bmRlZmluZWQsIHBvaW50KTtcblx0XHRcdFx0fSxcblx0XHRcdF0pO1xuXHRcdH0gZWxzZSBpZiAodGhpcy50b3VjaEdlc3R1cmVzKCkgIT09ICdvZmYnKSB7XG5cdFx0XHR0aGlzLl9kaXNhYmxlTmF0aXZlR2VzdHVyZXNJZk5lY2Vzc2FyeSgpO1xuXG5cdFx0XHR0aGlzLl9wYXNzaXZlTGlzdGVuZXJzLnB1c2goW1xuXHRcdFx0XHQndG91Y2hzdGFydCcsXG5cdFx0XHRcdChldmVudCkgPT4ge1xuXHRcdFx0XHRcdGNvbnN0IHRvdWNoID0gKGV2ZW50IGFzIFRvdWNoRXZlbnQpLnRhcmdldFRvdWNoZXM/LlswXTtcblx0XHRcdFx0XHRjb25zdCBvcmlnaW4gPSB0b3VjaCA/IHsgeDogdG91Y2guY2xpZW50WCwgeTogdG91Y2guY2xpZW50WSB9IDogdW5kZWZpbmVkO1xuXHRcdFx0XHRcdC8vIE5vdGUgdGhhdCBpdCdzIGltcG9ydGFudCB0aGF0IHdlIGRvbid0IGBwcmV2ZW50RGVmYXVsdGAgaGVyZSxcblx0XHRcdFx0XHQvLyBiZWNhdXNlIGl0IGNhbiBwcmV2ZW50IGNsaWNrIGV2ZW50cyBmcm9tIGZpcmluZyBvbiB0aGUgZWxlbWVudC5cblx0XHRcdFx0XHR0aGlzLl9zZXR1cFBvaW50ZXJFeGl0RXZlbnRzSWZOZWVkZWQoKTtcblx0XHRcdFx0XHRjbGVhclRpbWVvdXQodGhpcy5fdG91Y2hzdGFydFRpbWVvdXQpO1xuXHRcdFx0XHRcdHRoaXMuX3RvdWNoc3RhcnRUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB0aGlzLnNob3codW5kZWZpbmVkLCBvcmlnaW4pLCBMT05HUFJFU1NfREVMQVkpO1xuXHRcdFx0XHR9LFxuXHRcdFx0XSk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fYWRkTGlzdGVuZXJzKHRoaXMuX3Bhc3NpdmVMaXN0ZW5lcnMpO1xuXHR9XG5cblx0cHJpdmF0ZSBfc2V0dXBQb2ludGVyRXhpdEV2ZW50c0lmTmVlZGVkKCk6IHZvaWQge1xuXHRcdGlmICh0aGlzLl9wb2ludGVyRXhpdEV2ZW50c0luaXRpYWxpemVkKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdHRoaXMuX3BvaW50ZXJFeGl0RXZlbnRzSW5pdGlhbGl6ZWQgPSB0cnVlO1xuXG5cdFx0Y29uc3QgZXhpdExpc3RlbmVyczogKHJlYWRvbmx5IFtzdHJpbmcsIEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3RdKVtdID0gW107XG5cdFx0aWYgKHRoaXMuX3BsYXRmb3JtU3VwcG9ydHNNb3VzZUV2ZW50cygpKSB7XG5cdFx0XHRleGl0TGlzdGVuZXJzLnB1c2goXG5cdFx0XHRcdFtcblx0XHRcdFx0XHQnbW91c2VsZWF2ZScsXG5cdFx0XHRcdFx0KGV2ZW50KSA9PiB7XG5cdFx0XHRcdFx0XHRjb25zdCBuZXdUYXJnZXQgPSAoZXZlbnQgYXMgTW91c2VFdmVudCkucmVsYXRlZFRhcmdldCBhcyBOb2RlIHwgbnVsbDtcblx0XHRcdFx0XHRcdGlmICghbmV3VGFyZ2V0IHx8ICF0aGlzLl9vdmVybGF5UmVmPy5vdmVybGF5RWxlbWVudC5jb250YWlucyhuZXdUYXJnZXQpKSB7XG5cdFx0XHRcdFx0XHRcdHRoaXMuaGlkZSgpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdF0sXG5cdFx0XHRcdFsnd2hlZWwnLCAoZXZlbnQpID0+IHRoaXMuX3doZWVsTGlzdGVuZXIoZXZlbnQgYXMgV2hlZWxFdmVudCldLFxuXHRcdFx0KTtcblx0XHR9IGVsc2UgaWYgKHRoaXMudG91Y2hHZXN0dXJlcygpICE9PSAnb2ZmJykge1xuXHRcdFx0dGhpcy5fZGlzYWJsZU5hdGl2ZUdlc3R1cmVzSWZOZWNlc3NhcnkoKTtcblx0XHRcdGNvbnN0IHRvdWNoZW5kTGlzdGVuZXIgPSAoKSA9PiB7XG5cdFx0XHRcdGNsZWFyVGltZW91dCh0aGlzLl90b3VjaHN0YXJ0VGltZW91dCk7XG5cdFx0XHRcdHRoaXMuaGlkZSh0aGlzLl9kZWZhdWx0T3B0aW9ucz8udG91Y2hlbmRIaWRlRGVsYXkpO1xuXHRcdFx0fTtcblxuXHRcdFx0ZXhpdExpc3RlbmVycy5wdXNoKFsndG91Y2hlbmQnLCB0b3VjaGVuZExpc3RlbmVyXSwgWyd0b3VjaGNhbmNlbCcsIHRvdWNoZW5kTGlzdGVuZXJdKTtcblx0XHR9XG5cblx0XHR0aGlzLl9hZGRMaXN0ZW5lcnMoZXhpdExpc3RlbmVycyk7XG5cdFx0dGhpcy5fcGFzc2l2ZUxpc3RlbmVycy5wdXNoKC4uLmV4aXRMaXN0ZW5lcnMpO1xuXHR9XG5cblx0cHJpdmF0ZSBfYWRkTGlzdGVuZXJzKGxpc3RlbmVyczogKHJlYWRvbmx5IFtzdHJpbmcsIEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3RdKVtdKSB7XG5cdFx0bGlzdGVuZXJzLmZvckVhY2goKFtldmVudCwgbGlzdGVuZXJdKSA9PiB7XG5cdFx0XHR0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudCwgbGlzdGVuZXIsIHBhc3NpdmVMaXN0ZW5lck9wdGlvbnMpO1xuXHRcdH0pO1xuXHR9XG5cblx0cHJpdmF0ZSBfcGxhdGZvcm1TdXBwb3J0c01vdXNlRXZlbnRzKCk6IGJvb2xlYW4ge1xuXHRcdHJldHVybiAhdGhpcy5fcGxhdGZvcm0uSU9TICYmICF0aGlzLl9wbGF0Zm9ybS5BTkRST0lEO1xuXHR9XG5cblx0LyoqIExpc3RlbmVyIGZvciB0aGUgYHdoZWVsYCBldmVudCBvbiB0aGUgZWxlbWVudC4gKi9cblx0cHJpdmF0ZSBfd2hlZWxMaXN0ZW5lcihldmVudDogV2hlZWxFdmVudCkge1xuXHRcdGlmICh0aGlzLl9pc1Rvb2x0aXBWaXNpYmxlKCkpIHtcblx0XHRcdGNvbnN0IGVsZW1lbnRVbmRlclBvaW50ZXIgPSB0aGlzLl9kb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFkpO1xuXHRcdFx0Y29uc3QgZWxlbWVudCA9IHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcblxuXHRcdFx0Ly8gT24gbm9uLXRvdWNoIGRldmljZXMgd2UgZGVwZW5kIG9uIHRoZSBgbW91c2VsZWF2ZWAgZXZlbnQgdG8gY2xvc2UgdGhlIHRvb2x0aXAsIGJ1dCBpdFxuXHRcdFx0Ly8gd29uJ3QgZmlyZSBpZiB0aGUgdXNlciBzY3JvbGxzIGF3YXkgdXNpbmcgdGhlIHdoZWVsIHdpdGhvdXQgbW92aW5nIHRoZWlyIGN1cnNvci4gV2Vcblx0XHRcdC8vIHdvcmsgYXJvdW5kIGl0IGJ5IGZpbmRpbmcgdGhlIGVsZW1lbnQgdW5kZXIgdGhlIHVzZXIncyBjdXJzb3IgYW5kIGNsb3NpbmcgdGhlIHRvb2x0aXBcblx0XHRcdC8vIGlmIGl0J3Mgbm90IHRoZSB0cmlnZ2VyLlxuXHRcdFx0aWYgKGVsZW1lbnRVbmRlclBvaW50ZXIgIT09IGVsZW1lbnQgJiYgIWVsZW1lbnQuY29udGFpbnMoZWxlbWVudFVuZGVyUG9pbnRlcikpIHtcblx0XHRcdFx0dGhpcy5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0LyoqIERpc2FibGVzIHRoZSBuYXRpdmUgYnJvd3NlciBnZXN0dXJlcywgYmFzZWQgb24gaG93IHRoZSB0b29sdGlwIGhhcyBiZWVuIGNvbmZpZ3VyZWQuICovXG5cdHByaXZhdGUgX2Rpc2FibGVOYXRpdmVHZXN0dXJlc0lmTmVjZXNzYXJ5KCk6IHZvaWQge1xuXHRcdGNvbnN0IGdlc3R1cmVzID0gdGhpcy50b3VjaEdlc3R1cmVzKCk7XG5cblx0XHRpZiAoZ2VzdHVyZXMgIT09ICdvZmYnKSB7XG5cdFx0XHRjb25zdCBlbGVtZW50ID0gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuXHRcdFx0Y29uc3Qgc3R5bGUgPSBlbGVtZW50LnN0eWxlO1xuXG5cdFx0XHQvLyBJZiBnZXN0dXJlcyBhcmUgc2V0IHRvIGBhdXRvYCwgd2UgZG9uJ3QgZGlzYWJsZSB0ZXh0IHNlbGVjdGlvbiBvbiBpbnB1dHMgYW5kXG5cdFx0XHQvLyB0ZXh0YXJlYXMsIGJlY2F1c2UgaXQgcHJldmVudHMgdGhlIHVzZXIgZnJvbSB0eXBpbmcgaW50byB0aGVtIG9uIGlPUyBTYWZhcmkuXG5cdFx0XHRpZiAoZ2VzdHVyZXMgPT09ICdvbicgfHwgKGVsZW1lbnQubm9kZU5hbWUgIT09ICdJTlBVVCcgJiYgZWxlbWVudC5ub2RlTmFtZSAhPT0gJ1RFWFRBUkVBJykpIHtcblx0XHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcblx0XHRcdFx0c3R5bGUudXNlclNlbGVjdCA9IChzdHlsZSBhcyBhbnkpLm1zVXNlclNlbGVjdCA9IHN0eWxlLndlYmtpdFVzZXJTZWxlY3QgPSAoc3R5bGUgYXMgYW55KS5Nb3pVc2VyU2VsZWN0ID0gJ25vbmUnO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBJZiB3ZSBoYXZlIGBhdXRvYCBnZXN0dXJlcyBhbmQgdGhlIGVsZW1lbnQgdXNlcyBuYXRpdmUgSFRNTCBkcmFnZ2luZyxcblx0XHRcdC8vIHdlIGRvbid0IHNldCBgLXdlYmtpdC11c2VyLWRyYWdgIGJlY2F1c2UgaXQgcHJldmVudHMgdGhlIG5hdGl2ZSBiZWhhdmlvci5cblx0XHRcdGlmIChnZXN0dXJlcyA9PT0gJ29uJyB8fCAhZWxlbWVudC5kcmFnZ2FibGUpIHtcblx0XHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcblx0XHRcdFx0KHN0eWxlIGFzIGFueSkud2Via2l0VXNlckRyYWcgPSAnbm9uZSc7XG5cdFx0XHR9XG5cblx0XHRcdHN0eWxlLnRvdWNoQWN0aW9uID0gJ25vbmUnO1xuXHRcdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcblx0XHRcdChzdHlsZSBhcyBhbnkpLndlYmtpdFRhcEhpZ2hsaWdodENvbG9yID0gJ3RyYW5zcGFyZW50Jztcblx0XHR9XG5cdH1cbn1cbiJdfQ==
|