@angular/cdk 13.0.0-next.7 → 13.0.0-rc.2
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/a11y/a11y-module.d.ts +9 -7
- package/a11y/a11y_public_index.d.ts +4 -0
- package/a11y/aria-describer/aria-describer.d.ts +3 -7
- package/a11y/focus-monitor/focus-monitor.d.ts +5 -0
- package/a11y/focus-trap/configurable-focus-trap-factory.d.ts +3 -7
- package/a11y/focus-trap/focus-trap-manager.d.ts +3 -7
- package/a11y/focus-trap/focus-trap.d.ts +5 -0
- package/a11y/high-contrast-mode/high-contrast-mode-detector.d.ts +3 -0
- package/a11y/index.d.ts +5 -2
- package/a11y/input-modality/input-modality-detector.d.ts +3 -7
- package/a11y/interactivity-checker/interactivity-checker.d.ts +3 -0
- package/a11y/live-announcer/live-announcer.d.ts +6 -1
- package/a11y/package.json +6 -6
- package/accordion/accordion-item.d.ts +3 -0
- package/accordion/accordion-module.d.ts +6 -7
- package/accordion/accordion.d.ts +3 -0
- package/accordion/accordion_public_index.d.ts +4 -0
- package/accordion/index.d.ts +5 -2
- package/accordion/package.json +6 -6
- package/bidi/bidi-module.d.ts +5 -7
- package/bidi/bidi_public_index.d.ts +4 -0
- package/bidi/dir.d.ts +3 -0
- package/bidi/directionality.d.ts +3 -0
- package/bidi/index.d.ts +5 -2
- package/bidi/package.json +6 -6
- package/clipboard/clipboard-module.d.ts +5 -7
- package/clipboard/clipboard.d.ts +3 -7
- package/clipboard/clipboard_public_index.d.ts +4 -0
- package/clipboard/copy-to-clipboard.d.ts +3 -0
- package/clipboard/index.d.ts +5 -1
- package/clipboard/package.json +6 -6
- package/coercion/package.json +5 -5
- package/collections/collections_public_index.d.ts +4 -0
- package/collections/index.d.ts +5 -1
- package/collections/package.json +6 -6
- package/collections/unique-selection-dispatcher.d.ts +3 -0
- package/drag-drop/client-rect.d.ts +8 -1
- package/drag-drop/directives/drag-handle.d.ts +3 -0
- package/drag-drop/directives/drag-placeholder.d.ts +3 -0
- package/drag-drop/directives/drag-preview.d.ts +3 -0
- package/drag-drop/directives/drag.d.ts +3 -0
- package/drag-drop/directives/drop-list-group.d.ts +3 -0
- package/drag-drop/directives/drop-list.d.ts +3 -0
- package/drag-drop/drag-drop-module.d.ts +11 -7
- package/drag-drop/drag-drop-registry.d.ts +3 -0
- package/drag-drop/drag-drop.d.ts +3 -0
- package/drag-drop/drag-drop_public_index.d.ts +4 -0
- package/drag-drop/index.d.ts +5 -2
- package/drag-drop/package.json +6 -6
- package/esm2020/a11y/a11y-module.mjs +33 -0
- package/esm2020/a11y/a11y_public_index.mjs +5 -0
- package/esm2020/a11y/aria-describer/aria-describer.mjs +208 -0
- package/{esm2015/a11y/aria-describer/aria-reference.js → esm2020/a11y/aria-describer/aria-reference.mjs} +1 -1
- package/esm2020/a11y/fake-event-detection.mjs +29 -0
- package/esm2020/a11y/focus-monitor/focus-monitor.mjs +400 -0
- package/{esm2015/a11y/focus-trap/configurable-focus-trap-config.js → esm2020/a11y/focus-trap/configurable-focus-trap-config.mjs} +0 -0
- package/esm2020/a11y/focus-trap/configurable-focus-trap-factory.mjs +53 -0
- package/esm2020/a11y/focus-trap/configurable-focus-trap.mjs +51 -0
- package/esm2020/a11y/focus-trap/event-listener-inert-strategy.mjs +61 -0
- package/esm2020/a11y/focus-trap/focus-trap-inert-strategy.mjs +11 -0
- package/esm2020/a11y/focus-trap/focus-trap-manager.mjs +53 -0
- package/esm2020/a11y/focus-trap/focus-trap.mjs +399 -0
- package/esm2020/a11y/high-contrast-mode/high-contrast-mode-detector.mjs +95 -0
- package/esm2020/a11y/index.mjs +9 -0
- package/esm2020/a11y/input-modality/input-modality-detector.mjs +176 -0
- package/esm2020/a11y/interactivity-checker/interactivity-checker.mjs +238 -0
- package/{esm2015/a11y/key-manager/activedescendant-key-manager.js → esm2020/a11y/key-manager/activedescendant-key-manager.mjs} +1 -1
- package/{esm2015/a11y/key-manager/focus-key-manager.js → esm2020/a11y/key-manager/focus-key-manager.mjs} +0 -0
- package/esm2020/a11y/key-manager/list-key-manager.mjs +321 -0
- package/esm2020/a11y/live-announcer/live-announcer-tokens.mjs +19 -0
- package/esm2020/a11y/live-announcer/live-announcer.mjs +170 -0
- package/{esm2015/a11y/public-api.js → esm2020/a11y/public-api.mjs} +0 -0
- package/esm2020/accordion/accordion-item.mjs +167 -0
- package/esm2020/accordion/accordion-module.mjs +24 -0
- package/esm2020/accordion/accordion.mjs +70 -0
- package/esm2020/accordion/accordion_public_index.mjs +5 -0
- package/esm2020/accordion/index.mjs +9 -0
- package/{esm2015/accordion/public-api.js → esm2020/accordion/public-api.mjs} +0 -0
- package/esm2020/bidi/bidi-module.mjs +23 -0
- package/esm2020/bidi/bidi_public_index.mjs +5 -0
- package/{esm2015/bidi/dir-document-token.js → esm2020/bidi/dir-document-token.mjs} +1 -1
- package/esm2020/bidi/dir.mjs +67 -0
- package/esm2020/bidi/directionality.mjs +47 -0
- package/esm2020/bidi/index.mjs +9 -0
- package/{esm2015/bidi/public-api.js → esm2020/bidi/public-api.mjs} +1 -1
- package/esm2020/clipboard/clipboard-module.mjs +23 -0
- package/esm2020/clipboard/clipboard.mjs +53 -0
- package/esm2020/clipboard/clipboard_public_index.mjs +5 -0
- package/esm2020/clipboard/copy-to-clipboard.mjs +99 -0
- package/esm2020/clipboard/index.mjs +9 -0
- package/esm2020/clipboard/pending-copy.mjs +67 -0
- package/{esm2015/clipboard/public-api.js → esm2020/clipboard/public-api.mjs} +0 -0
- package/{esm2015/coercion/array.js → esm2020/coercion/array.mjs} +0 -0
- package/{esm2015/coercion/boolean-property.js → esm2020/coercion/boolean-property.mjs} +0 -0
- package/{esm2015/coercion/css-pixel-value.js → esm2020/coercion/css-pixel-value.mjs} +0 -0
- package/{esm2015/coercion/element.js → esm2020/coercion/element.mjs} +0 -0
- package/{esm2015/coercion/index.js → esm2020/coercion/index.mjs} +0 -0
- package/{esm2015/coercion/number-property.js → esm2020/coercion/number-property.mjs} +0 -0
- package/{esm2015/coercion/public-api.js → esm2020/coercion/public-api.mjs} +0 -0
- package/{esm2015/coercion/string-array.js → esm2020/coercion/string-array.mjs} +0 -0
- package/{esm2015/collections/array-data-source.js → esm2020/collections/array-data-source.mjs} +1 -1
- package/esm2020/collections/collection-viewer.mjs +9 -0
- package/esm2020/collections/collections_public_index.mjs +5 -0
- package/{esm2015/collections/data-source.js → esm2020/collections/data-source.mjs} +0 -0
- package/esm2020/collections/dispose-view-repeater-strategy.mjs +47 -0
- package/esm2020/collections/index.mjs +9 -0
- package/{esm2015/collections/public-api.js → esm2020/collections/public-api.mjs} +0 -0
- package/esm2020/collections/recycle-view-repeater-strategy.mjs +128 -0
- package/{esm2015/collections/selection-model.js → esm2020/collections/selection-model.mjs} +2 -2
- package/esm2020/collections/tree-adapter.mjs +9 -0
- package/esm2020/collections/unique-selection-dispatcher.mjs +55 -0
- package/esm2020/collections/view-repeater.mjs +14 -0
- package/esm2020/drag-drop/client-rect.mjs +64 -0
- package/esm2020/drag-drop/clone-node.mjs +65 -0
- package/esm2020/drag-drop/directives/assertions.mjs +18 -0
- package/{esm2015/drag-drop/directives/config.js → esm2020/drag-drop/directives/config.mjs} +1 -1
- package/esm2020/drag-drop/directives/drag-handle.mjs +66 -0
- package/esm2020/drag-drop/directives/drag-placeholder.mjs +36 -0
- package/esm2020/drag-drop/directives/drag-preview.mjs +47 -0
- package/esm2020/drag-drop/directives/drag.mjs +483 -0
- package/esm2020/drag-drop/directives/drop-list-group.mjs +53 -0
- package/esm2020/drag-drop/directives/drop-list.mjs +344 -0
- package/esm2020/drag-drop/drag-drop-module.mjs +57 -0
- package/esm2020/drag-drop/drag-drop-registry.mjs +231 -0
- package/esm2020/drag-drop/drag-drop.mjs +57 -0
- package/esm2020/drag-drop/drag-drop_public_index.mjs +5 -0
- package/esm2020/drag-drop/drag-events.mjs +9 -0
- package/{esm2015/drag-drop/drag-parent.js → esm2020/drag-drop/drag-parent.mjs} +0 -0
- package/esm2020/drag-drop/drag-ref.mjs +1108 -0
- package/esm2020/drag-drop/drag-styling.mjs +69 -0
- package/esm2020/drag-drop/drag-utils.mjs +60 -0
- package/esm2020/drag-drop/drop-list-ref.mjs +830 -0
- package/esm2020/drag-drop/index.mjs +9 -0
- package/{esm2015/drag-drop/parent-position-tracker.js → esm2020/drag-drop/parent-position-tracker.mjs} +2 -2
- package/{esm2015/drag-drop/public-api.js → esm2020/drag-drop/public-api.mjs} +0 -0
- package/esm2020/drag-drop/transition-duration.mjs +36 -0
- package/{esm2015/index.js → esm2020/index.mjs} +0 -0
- package/esm2020/keycodes/index.mjs +9 -0
- package/{esm2015/keycodes/keycodes.js → esm2020/keycodes/keycodes.mjs} +1 -1
- package/esm2020/keycodes/keycodes_public_index.mjs +5 -0
- package/{esm2015/keycodes/modifiers.js → esm2020/keycodes/modifiers.mjs} +0 -0
- package/{esm2015/keycodes/public-api.js → esm2020/keycodes/public-api.mjs} +0 -0
- package/esm2020/layout/breakpoints-observer.mjs +105 -0
- package/{esm2015/layout/breakpoints.js → esm2020/layout/breakpoints.mjs} +1 -1
- package/esm2020/layout/index.mjs +9 -0
- package/esm2020/layout/layout-module.mjs +19 -0
- package/esm2020/layout/layout_public_index.mjs +5 -0
- package/esm2020/layout/media-matcher.mjs +85 -0
- package/{esm2015/layout/public-api.js → esm2020/layout/public-api.mjs} +0 -0
- package/esm2020/observers/index.mjs +9 -0
- package/esm2020/observers/observe-content.mjs +187 -0
- package/esm2020/observers/observers_public_index.mjs +5 -0
- package/{esm2015/observers/public-api.js → esm2020/observers/public-api.mjs} +0 -0
- package/esm2020/overlay/dispatchers/base-overlay-dispatcher.mjs +52 -0
- package/{esm2015/overlay/dispatchers/index.js → esm2020/overlay/dispatchers/index.mjs} +0 -0
- package/esm2020/overlay/dispatchers/overlay-keyboard-dispatcher.mjs +63 -0
- package/esm2020/overlay/dispatchers/overlay-outside-click-dispatcher.mjs +116 -0
- package/esm2020/overlay/fullscreen-overlay-container.mjs +94 -0
- package/esm2020/overlay/index.mjs +9 -0
- package/esm2020/overlay/overlay-config.mjs +45 -0
- package/esm2020/overlay/overlay-container.mjs +81 -0
- package/esm2020/overlay/overlay-directives.mjs +427 -0
- package/esm2020/overlay/overlay-module.mjs +29 -0
- package/esm2020/overlay/overlay-ref.mjs +402 -0
- package/{esm2015/overlay/overlay-reference.js → esm2020/overlay/overlay-reference.mjs} +0 -0
- package/esm2020/overlay/overlay.mjs +119 -0
- package/esm2020/overlay/overlay_public_index.mjs +5 -0
- package/esm2020/overlay/position/connected-position.mjs +97 -0
- package/esm2020/overlay/position/flexible-connected-position-strategy.mjs +959 -0
- package/esm2020/overlay/position/global-position-strategy.mjs +203 -0
- package/esm2020/overlay/position/overlay-position-builder.mjs +50 -0
- package/{esm2015/overlay/position/position-strategy.js → esm2020/overlay/position/position-strategy.mjs} +0 -0
- package/esm2020/overlay/position/scroll-clip.mjs +40 -0
- package/{esm2015/overlay/public-api.js → esm2020/overlay/public-api.mjs} +0 -0
- package/{esm2015/overlay/scroll/block-scroll-strategy.js → esm2020/overlay/scroll/block-scroll-strategy.mjs} +1 -1
- package/esm2020/overlay/scroll/close-scroll-strategy.mjs +61 -0
- package/{esm2015/overlay/scroll/index.js → esm2020/overlay/scroll/index.mjs} +2 -2
- package/{esm2015/overlay/scroll/noop-scroll-strategy.js → esm2020/overlay/scroll/noop-scroll-strategy.mjs} +1 -1
- package/{esm2015/overlay/scroll/reposition-scroll-strategy.js → esm2020/overlay/scroll/reposition-scroll-strategy.mjs} +1 -1
- package/esm2020/overlay/scroll/scroll-strategy-options.mjs +55 -0
- package/{esm2015/overlay/scroll/scroll-strategy.js → esm2020/overlay/scroll/scroll-strategy.mjs} +0 -0
- package/{esm2015/platform/features/input-types.js → esm2020/platform/features/input-types.mjs} +1 -1
- package/esm2020/platform/features/passive-listeners.mjs +36 -0
- package/esm2020/platform/features/scrolling.mjs +85 -0
- package/{esm2015/platform/features/shadow-dom.js → esm2020/platform/features/shadow-dom.mjs} +4 -3
- package/esm2020/platform/features/test-environment.mjs +27 -0
- package/esm2020/platform/index.mjs +9 -0
- package/esm2020/platform/platform-module.mjs +19 -0
- package/esm2020/platform/platform.mjs +85 -0
- package/esm2020/platform/platform_public_index.mjs +5 -0
- package/{esm2015/platform/public-api.js → esm2020/platform/public-api.mjs} +0 -0
- package/esm2020/portal/dom-portal-outlet.mjs +134 -0
- package/esm2020/portal/index.mjs +9 -0
- package/esm2020/portal/portal-directives.mjs +244 -0
- package/{esm2015/portal/portal-errors.js → esm2020/portal/portal-errors.mjs} +1 -1
- package/esm2020/portal/portal-injector.mjs +28 -0
- package/esm2020/portal/portal.mjs +179 -0
- package/esm2020/portal/portal_public_index.mjs +5 -0
- package/{esm2015/portal/public-api.js → esm2020/portal/public-api.mjs} +0 -0
- package/{esm2015/public-api.js → esm2020/public-api.mjs} +0 -0
- package/esm2020/scrolling/fixed-size-virtual-scroll.mjs +217 -0
- package/esm2020/scrolling/index.mjs +9 -0
- package/{esm2015/scrolling/public-api.js → esm2020/scrolling/public-api.mjs} +0 -0
- package/esm2020/scrolling/scroll-dispatcher.mjs +163 -0
- package/esm2020/scrolling/scrollable.mjs +176 -0
- package/esm2020/scrolling/scrolling-module.mjs +52 -0
- package/esm2020/scrolling/scrolling_public_index.mjs +5 -0
- package/esm2020/scrolling/viewport-ruler.mjs +146 -0
- package/esm2020/scrolling/virtual-for-of.mjs +296 -0
- package/{esm2015/scrolling/virtual-scroll-repeater.js → esm2020/scrolling/virtual-scroll-repeater.mjs} +0 -0
- package/esm2020/scrolling/virtual-scroll-strategy.mjs +11 -0
- package/esm2020/scrolling/virtual-scroll-viewport.mjs +378 -0
- package/esm2020/stepper/index.mjs +9 -0
- package/{esm2015/stepper/public-api.js → esm2020/stepper/public-api.mjs} +0 -0
- package/esm2020/stepper/step-header.mjs +30 -0
- package/esm2020/stepper/step-label.mjs +23 -0
- package/esm2020/stepper/stepper-button.mjs +76 -0
- package/esm2020/stepper/stepper-module.mjs +40 -0
- package/esm2020/stepper/stepper.mjs +471 -0
- package/esm2020/stepper/stepper_public_index.mjs +5 -0
- package/esm2020/table/can-stick.mjs +44 -0
- package/esm2020/table/cell.mjs +222 -0
- package/esm2020/table/coalesced-style-scheduler.mjs +91 -0
- package/esm2020/table/index.mjs +9 -0
- package/{esm2015/table/public-api.js → esm2020/table/public-api.mjs} +0 -0
- package/esm2020/table/row.mjs +254 -0
- package/esm2020/table/sticky-position-listener.mjs +11 -0
- package/esm2020/table/sticky-styler.mjs +345 -0
- package/{esm2015/table/table-errors.js → esm2020/table/table-errors.mjs} +1 -1
- package/esm2020/table/table-module.mjs +94 -0
- package/esm2020/table/table.mjs +1023 -0
- package/esm2020/table/table_public_index.mjs +5 -0
- package/esm2020/table/text-column.mjs +153 -0
- package/{esm2015/table/tokens.js → esm2020/table/tokens.mjs} +1 -1
- package/esm2020/testing/change-detection.mjs +102 -0
- package/esm2020/testing/component-harness.mjs +322 -0
- package/{esm2015/testing/element-dimensions.js → esm2020/testing/element-dimensions.mjs} +1 -1
- package/esm2020/testing/harness-environment.mjs +202 -0
- package/{esm2015/testing/index.js → esm2020/testing/index.mjs} +0 -0
- package/{esm2015/testing/protractor/index.js → esm2020/testing/protractor/index.mjs} +0 -0
- package/esm2020/testing/protractor/protractor-element.mjs +234 -0
- package/esm2020/testing/protractor/protractor-harness-environment.mjs +72 -0
- package/{esm2015/testing/protractor/public-api.js → esm2020/testing/protractor/public-api.mjs} +0 -0
- package/{esm2015/testing/public-api.js → esm2020/testing/public-api.mjs} +0 -0
- package/{esm2015/testing/selenium-webdriver/index.js → esm2020/testing/selenium-webdriver/index.mjs} +0 -0
- package/{esm2015/testing/selenium-webdriver/public-api.js → esm2020/testing/selenium-webdriver/public-api.mjs} +0 -0
- package/esm2020/testing/selenium-webdriver/selenium-web-driver-element.mjs +199 -0
- package/esm2020/testing/selenium-webdriver/selenium-web-driver-harness-environment.mjs +87 -0
- package/{esm2015/testing/selenium-webdriver/selenium-webdriver-keys.js → esm2020/testing/selenium-webdriver/selenium-webdriver-keys.mjs} +2 -2
- package/esm2020/testing/test-element.mjs +48 -0
- package/esm2020/testing/testbed/fake-events/dispatch-events.mjs +53 -0
- package/esm2020/testing/testbed/fake-events/element-focus.mjs +39 -0
- package/esm2020/testing/testbed/fake-events/event-objects.mjs +113 -0
- package/{esm2015/testing/testbed/fake-events/index.js → esm2020/testing/testbed/fake-events/index.mjs} +0 -0
- package/esm2020/testing/testbed/fake-events/type-in-element.mjs +88 -0
- package/{esm2015/testing/testbed/index.js → esm2020/testing/testbed/index.mjs} +0 -0
- package/{esm2015/testing/testbed/public-api.js → esm2020/testing/testbed/public-api.mjs} +0 -0
- package/esm2020/testing/testbed/task-state-zone-interceptor.mjs +82 -0
- package/esm2020/testing/testbed/testbed-harness-environment.mjs +162 -0
- package/esm2020/testing/testbed/unit-test-element.mjs +224 -0
- package/esm2020/testing/text-filtering.mjs +21 -0
- package/esm2020/text-field/autofill.mjs +113 -0
- package/esm2020/text-field/autosize.mjs +310 -0
- package/esm2020/text-field/index.mjs +9 -0
- package/{esm2015/text-field/public-api.js → esm2020/text-field/public-api.mjs} +0 -0
- package/esm2020/text-field/text-field-module.mjs +26 -0
- package/esm2020/text-field/text-field_public_index.mjs +5 -0
- package/{esm2015/tree/control/base-tree-control.js → esm2020/tree/control/base-tree-control.mjs} +4 -4
- package/{esm2015/tree/control/flat-tree-control.js → esm2020/tree/control/flat-tree-control.mjs} +1 -1
- package/esm2020/tree/control/nested-tree-control.mjs +58 -0
- package/{esm2015/tree/control/tree-control.js → esm2020/tree/control/tree-control.mjs} +0 -0
- package/esm2020/tree/index.mjs +9 -0
- package/esm2020/tree/nested-node.mjs +117 -0
- package/esm2020/tree/node.mjs +35 -0
- package/esm2020/tree/outlet.mjs +39 -0
- package/esm2020/tree/padding.mjs +131 -0
- package/{esm2015/tree/public-api.js → esm2020/tree/public-api.mjs} +0 -0
- package/esm2020/tree/toggle.mjs +53 -0
- package/{esm2015/tree/tree-errors.js → esm2020/tree/tree-errors.mjs} +0 -0
- package/esm2020/tree/tree-module.mjs +49 -0
- package/esm2020/tree/tree.mjs +361 -0
- package/esm2020/tree/tree_public_index.mjs +5 -0
- package/{esm2015/version.js → esm2020/version.mjs} +1 -1
- package/fesm2015/{a11y.js → a11y.mjs} +289 -254
- package/fesm2015/a11y.mjs.map +1 -0
- package/fesm2015/accordion.mjs +275 -0
- package/fesm2015/accordion.mjs.map +1 -0
- package/fesm2015/bidi.mjs +187 -0
- package/fesm2015/bidi.mjs.map +1 -0
- package/fesm2015/{cdk.js → cdk.mjs} +2 -2
- package/fesm2015/cdk.mjs.map +1 -0
- package/fesm2015/clipboard.mjs +261 -0
- package/fesm2015/clipboard.mjs.map +1 -0
- package/fesm2015/{coercion.js → coercion.mjs} +1 -1
- package/fesm2015/coercion.mjs.map +1 -0
- package/fesm2015/{collections.js → collections.mjs} +20 -24
- package/fesm2015/collections.mjs.map +1 -0
- package/fesm2015/drag-drop.mjs +3675 -0
- package/fesm2015/drag-drop.mjs.map +1 -0
- package/fesm2015/{keycodes.js → keycodes.mjs} +9 -1
- package/fesm2015/keycodes.mjs.map +1 -0
- package/fesm2015/{layout.js → layout.mjs} +38 -28
- package/fesm2015/layout.mjs.map +1 -0
- package/fesm2015/{observers.js → observers.mjs} +58 -41
- package/fesm2015/observers.mjs.map +1 -0
- package/fesm2015/overlay.mjs +3012 -0
- package/fesm2015/overlay.mjs.map +1 -0
- package/fesm2015/platform.mjs +388 -0
- package/fesm2015/platform.mjs.map +1 -0
- package/fesm2015/portal.mjs +657 -0
- package/fesm2015/portal.mjs.map +1 -0
- package/fesm2015/scrolling.mjs +1402 -0
- package/fesm2015/scrolling.mjs.map +1 -0
- package/fesm2015/{stepper.js → stepper.mjs} +194 -133
- package/fesm2015/stepper.mjs.map +1 -0
- package/fesm2015/{table.js → table.mjs} +508 -359
- package/fesm2015/table.mjs.map +1 -0
- package/fesm2015/testing/{protractor.js → protractor.mjs} +12 -25
- package/fesm2015/testing/protractor.mjs.map +1 -0
- package/fesm2015/testing/{selenium-webdriver.js → selenium-webdriver.mjs} +14 -28
- package/fesm2015/testing/selenium-webdriver.mjs.map +1 -0
- package/fesm2015/testing/{testbed.js → testbed.mjs} +23 -29
- package/fesm2015/testing/testbed.mjs.map +1 -0
- package/fesm2015/{testing.js → testing.mjs} +19 -45
- package/fesm2015/testing.mjs.map +1 -0
- package/fesm2015/text-field.mjs +463 -0
- package/fesm2015/text-field.mjs.map +1 -0
- package/fesm2015/{tree.js → tree.mjs} +206 -152
- package/fesm2015/tree.mjs.map +1 -0
- package/fesm2020/a11y.mjs +2376 -0
- package/fesm2020/a11y.mjs.map +1 -0
- package/{fesm2015/accordion.js → fesm2020/accordion.mjs} +95 -57
- package/fesm2020/accordion.mjs.map +1 -0
- package/{fesm2015/bidi.js → fesm2020/bidi.mjs} +55 -31
- package/fesm2020/bidi.mjs.map +1 -0
- package/fesm2020/cdk.mjs +30 -0
- package/fesm2020/cdk.mjs.map +1 -0
- package/{fesm2015/clipboard.js → fesm2020/clipboard.mjs} +59 -40
- package/fesm2020/clipboard.mjs.map +1 -0
- package/fesm2020/coercion.mjs +132 -0
- package/fesm2020/coercion.mjs.map +1 -0
- package/fesm2020/collections.mjs +480 -0
- package/fesm2020/collections.mjs.map +1 -0
- package/{fesm2015/drag-drop.js → fesm2020/drag-drop.mjs} +528 -369
- package/fesm2020/drag-drop.mjs.map +1 -0
- package/fesm2020/keycodes.mjs +167 -0
- package/fesm2020/keycodes.mjs.map +1 -0
- package/fesm2020/layout.mjs +254 -0
- package/fesm2020/layout.mjs.map +1 -0
- package/fesm2020/observers.mjs +210 -0
- package/fesm2020/observers.mjs.map +1 -0
- package/{fesm2015/overlay.js → fesm2020/overlay.mjs} +320 -228
- package/fesm2020/overlay.mjs.map +1 -0
- package/{fesm2015/platform.js → fesm2020/platform.mjs} +60 -28
- package/fesm2020/platform.mjs.map +1 -0
- package/{fesm2015/portal.js → fesm2020/portal.mjs} +93 -64
- package/fesm2020/portal.mjs.map +1 -0
- package/{fesm2015/scrolling.js → fesm2020/scrolling.mjs} +221 -170
- package/fesm2020/scrolling.mjs.map +1 -0
- package/fesm2020/stepper.mjs +646 -0
- package/fesm2020/stepper.mjs.map +1 -0
- package/fesm2020/table.mjs +2303 -0
- package/fesm2020/table.mjs.map +1 -0
- package/fesm2020/testing/protractor.mjs +322 -0
- package/fesm2020/testing/protractor.mjs.map +1 -0
- package/fesm2020/testing/selenium-webdriver.mjs +362 -0
- package/fesm2020/testing/selenium-webdriver.mjs.map +1 -0
- package/fesm2020/testing/testbed.mjs +780 -0
- package/fesm2020/testing/testbed.mjs.map +1 -0
- package/fesm2020/testing.mjs +719 -0
- package/fesm2020/testing.mjs.map +1 -0
- package/{fesm2015/text-field.js → fesm2020/text-field.mjs} +91 -68
- package/fesm2020/text-field.mjs.map +1 -0
- package/fesm2020/tree.mjs +975 -0
- package/fesm2020/tree.mjs.map +1 -0
- package/keycodes/index.d.ts +5 -1
- package/keycodes/keycodes_public_index.d.ts +4 -0
- package/keycodes/package.json +6 -6
- package/layout/breakpoints-observer.d.ts +3 -7
- package/layout/index.d.ts +5 -1
- package/layout/layout-module.d.ts +4 -0
- package/layout/layout_public_index.d.ts +4 -0
- package/layout/media-matcher.d.ts +3 -0
- package/layout/package.json +6 -6
- package/observers/index.d.ts +5 -1
- package/observers/observe-content.d.ts +10 -0
- package/observers/observers_public_index.d.ts +4 -0
- package/observers/package.json +6 -6
- package/overlay/dispatchers/base-overlay-dispatcher.d.ts +3 -7
- package/overlay/dispatchers/overlay-keyboard-dispatcher.d.ts +3 -7
- package/overlay/dispatchers/overlay-outside-click-dispatcher.d.ts +6 -7
- package/overlay/fullscreen-overlay-container.d.ts +3 -0
- package/overlay/index.d.ts +5 -3
- package/overlay/overlay-container.d.ts +3 -7
- package/overlay/overlay-directives.d.ts +5 -0
- package/overlay/overlay-module.d.ts +8 -7
- package/overlay/overlay.d.ts +3 -0
- package/overlay/overlay_public_index.d.ts +4 -0
- package/overlay/package.json +6 -6
- package/overlay/position/flexible-connected-position-strategy.d.ts +2 -2
- package/overlay/position/overlay-position-builder.d.ts +3 -0
- package/overlay/position/scroll-clip.d.ts +5 -2
- package/overlay/scroll/index.d.ts +1 -1
- package/overlay/scroll/scroll-strategy-options.d.ts +3 -0
- package/package.json +219 -7
- package/platform/index.d.ts +5 -1
- package/platform/package.json +6 -6
- package/platform/platform-module.d.ts +4 -7
- package/platform/platform.d.ts +3 -7
- package/platform/platform_public_index.d.ts +4 -0
- package/portal/index.d.ts +5 -1
- package/portal/package.json +6 -6
- package/portal/portal-directives.d.ts +12 -0
- package/portal/portal_public_index.d.ts +4 -0
- package/schematics/ng-add/index.js +3 -3
- package/schematics/ng-add/index.mjs +3 -3
- package/schematics/ng-add/package-config.js +4 -2
- package/schematics/ng-add/package-config.mjs +4 -2
- package/schematics/ng-add/schema.js +1 -1
- package/schematics/ng-add/schema.mjs +1 -1
- package/schematics/ng-generate/drag-drop/index.js +6 -6
- package/schematics/ng-generate/drag-drop/index.mjs +6 -6
- package/schematics/ng-update/data/attribute-selectors.js +7 -5
- package/schematics/ng-update/data/attribute-selectors.mjs +7 -5
- package/schematics/ng-update/data/class-names.js +13 -11
- package/schematics/ng-update/data/class-names.mjs +13 -11
- package/schematics/ng-update/data/constructor-checks.js +28 -20
- package/schematics/ng-update/data/constructor-checks.mjs +28 -20
- package/schematics/ng-update/data/css-selectors.js +2 -2
- package/schematics/ng-update/data/css-selectors.mjs +2 -2
- package/schematics/ng-update/data/element-selectors.js +2 -2
- package/schematics/ng-update/data/element-selectors.mjs +2 -2
- package/schematics/ng-update/data/input-names.js +40 -16
- package/schematics/ng-update/data/input-names.mjs +40 -16
- package/schematics/ng-update/data/method-call-checks.js +32 -18
- package/schematics/ng-update/data/method-call-checks.mjs +32 -18
- package/schematics/ng-update/data/output-names.js +8 -6
- package/schematics/ng-update/data/output-names.mjs +8 -6
- package/schematics/ng-update/data/property-names.js +40 -32
- package/schematics/ng-update/data/property-names.mjs +40 -32
- package/schematics/ng-update/devkit-file-system.js +2 -2
- package/schematics/ng-update/devkit-file-system.mjs +2 -2
- package/schematics/ng-update/devkit-migration-rule.js +8 -7
- package/schematics/ng-update/devkit-migration-rule.mjs +8 -7
- package/schematics/ng-update/devkit-migration.d.ts +3 -2
- package/schematics/ng-update/devkit-migration.js +1 -1
- package/schematics/ng-update/devkit-migration.mjs +1 -1
- package/schematics/ng-update/find-stylesheets.js +3 -3
- package/schematics/ng-update/find-stylesheets.mjs +3 -3
- package/schematics/ng-update/html-parsing/angular.js +7 -7
- package/schematics/ng-update/html-parsing/angular.mjs +7 -7
- package/schematics/ng-update/html-parsing/elements.js +2 -2
- package/schematics/ng-update/html-parsing/elements.mjs +2 -2
- package/schematics/ng-update/index.js +11 -9
- package/schematics/ng-update/index.mjs +11 -9
- package/schematics/ng-update/migrations/attribute-selectors.js +11 -7
- package/schematics/ng-update/migrations/attribute-selectors.mjs +11 -7
- package/schematics/ng-update/migrations/class-inheritance.js +3 -3
- package/schematics/ng-update/migrations/class-inheritance.mjs +3 -3
- package/schematics/ng-update/migrations/class-names.js +7 -6
- package/schematics/ng-update/migrations/class-names.mjs +7 -6
- package/schematics/ng-update/migrations/constructor-signature.js +16 -13
- package/schematics/ng-update/migrations/constructor-signature.mjs +16 -13
- package/schematics/ng-update/migrations/css-selectors.js +7 -6
- package/schematics/ng-update/migrations/css-selectors.mjs +7 -6
- package/schematics/ng-update/migrations/element-selectors.js +7 -6
- package/schematics/ng-update/migrations/element-selectors.mjs +7 -6
- package/schematics/ng-update/migrations/input-names.js +8 -9
- package/schematics/ng-update/migrations/input-names.mjs +8 -9
- package/schematics/ng-update/migrations/method-call-arguments.js +4 -3
- package/schematics/ng-update/migrations/method-call-arguments.mjs +4 -3
- package/schematics/ng-update/migrations/misc-template.js +3 -3
- package/schematics/ng-update/migrations/misc-template.mjs +3 -3
- package/schematics/ng-update/migrations/output-names.js +7 -8
- package/schematics/ng-update/migrations/output-names.mjs +7 -8
- package/schematics/ng-update/migrations/property-names.js +4 -3
- package/schematics/ng-update/migrations/property-names.mjs +4 -3
- package/schematics/ng-update/migrations/symbol-removal.js +2 -2
- package/schematics/ng-update/migrations/symbol-removal.mjs +2 -2
- package/schematics/ng-update/migrations/tilde-import-v13/tilde-import-migration.d.ts +14 -0
- package/schematics/ng-update/migrations/tilde-import-v13/tilde-import-migration.js +38 -0
- package/schematics/ng-update/migrations/tilde-import-v13/tilde-import-migration.mjs +38 -0
- package/schematics/ng-update/typescript/base-types.js +1 -1
- package/schematics/ng-update/typescript/base-types.mjs +1 -1
- package/schematics/ng-update/typescript/literal.d.ts +1 -1
- package/schematics/ng-update/typescript/literal.js +1 -1
- package/schematics/ng-update/typescript/literal.mjs +1 -1
- package/schematics/ng-update/typescript/module-specifiers.js +5 -5
- package/schematics/ng-update/typescript/module-specifiers.mjs +5 -5
- package/schematics/ng-update/upgrade-data.js +2 -2
- package/schematics/ng-update/upgrade-data.mjs +2 -2
- package/schematics/package.json +3 -0
- package/schematics/paths.js +3 -3
- package/schematics/paths.mjs +3 -3
- package/schematics/update-tool/component-resource-collector.js +10 -10
- package/schematics/update-tool/component-resource-collector.mjs +10 -10
- package/schematics/update-tool/file-system.js +1 -1
- package/schematics/update-tool/file-system.mjs +1 -1
- package/schematics/update-tool/index.d.ts +4 -1
- package/schematics/update-tool/index.js +9 -5
- package/schematics/update-tool/index.mjs +9 -5
- package/schematics/update-tool/migration.d.ts +1 -1
- package/schematics/update-tool/migration.js +1 -1
- package/schematics/update-tool/migration.mjs +1 -1
- package/schematics/update-tool/target-version.js +1 -1
- package/schematics/update-tool/target-version.mjs +1 -1
- package/schematics/update-tool/utils/decorators.js +8 -4
- package/schematics/update-tool/utils/decorators.mjs +8 -4
- package/schematics/update-tool/utils/functions.js +1 -1
- package/schematics/update-tool/utils/functions.mjs +1 -1
- package/schematics/update-tool/utils/imports.js +2 -2
- package/schematics/update-tool/utils/imports.mjs +2 -2
- package/schematics/update-tool/utils/line-mappings.js +1 -1
- package/schematics/update-tool/utils/line-mappings.mjs +1 -1
- package/schematics/update-tool/utils/parse-tsconfig.js +2 -2
- package/schematics/update-tool/utils/parse-tsconfig.mjs +2 -2
- package/schematics/update-tool/utils/property-name.js +1 -1
- package/schematics/update-tool/utils/property-name.mjs +1 -1
- package/schematics/update-tool/utils/virtual-host.d.ts +1 -1
- package/schematics/update-tool/utils/virtual-host.js +3 -3
- package/schematics/update-tool/utils/virtual-host.mjs +3 -3
- package/schematics/update-tool/version-changes.js +1 -1
- package/schematics/update-tool/version-changes.mjs +1 -1
- package/schematics/utils/ast/ng-module-imports.js +5 -3
- package/schematics/utils/ast/ng-module-imports.mjs +5 -3
- package/schematics/utils/ast.js +5 -5
- package/schematics/utils/ast.mjs +5 -5
- package/schematics/utils/build-component.js +32 -38
- package/schematics/utils/build-component.mjs +32 -38
- package/schematics/utils/get-project.js +1 -1
- package/schematics/utils/get-project.mjs +1 -1
- package/schematics/utils/html-manipulation.js +8 -7
- package/schematics/utils/html-manipulation.mjs +8 -7
- package/schematics/utils/parse5-element.js +9 -10
- package/schematics/utils/parse5-element.mjs +9 -10
- package/schematics/utils/project-index-file.js +2 -2
- package/schematics/utils/project-index-file.mjs +2 -2
- package/schematics/utils/project-main-file.js +2 -2
- package/schematics/utils/project-main-file.mjs +2 -2
- package/schematics/utils/project-style-file.js +7 -9
- package/schematics/utils/project-style-file.mjs +7 -9
- package/schematics/utils/project-targets.js +1 -1
- package/schematics/utils/project-targets.mjs +1 -1
- package/schematics/utils/project-tsconfig-paths.js +4 -4
- package/schematics/utils/project-tsconfig-paths.mjs +4 -4
- package/schematics/utils/schematic-options.js +7 -5
- package/schematics/utils/schematic-options.mjs +7 -5
- package/schematics/utils/vendored-ast-utils/index.js +17 -18
- package/schematics/utils/vendored-ast-utils/index.mjs +17 -18
- package/scrolling/fixed-size-virtual-scroll.d.ts +3 -0
- package/scrolling/index.d.ts +5 -1
- package/scrolling/package.json +6 -6
- package/scrolling/scroll-dispatcher.d.ts +3 -7
- package/scrolling/scrollable.d.ts +3 -0
- package/scrolling/scrolling-module.d.ts +13 -7
- package/scrolling/scrolling_public_index.d.ts +4 -0
- package/scrolling/viewport-ruler.d.ts +11 -1
- package/scrolling/virtual-for-of.d.ts +3 -0
- package/scrolling/virtual-scroll-viewport.d.ts +3 -0
- package/stepper/index.d.ts +5 -1
- package/stepper/package.json +6 -6
- package/stepper/step-header.d.ts +3 -0
- package/stepper/step-label.d.ts +3 -0
- package/stepper/stepper-button.d.ts +5 -7
- package/stepper/stepper-module.d.ts +9 -7
- package/stepper/stepper.d.ts +5 -7
- package/stepper/stepper_public_index.d.ts +4 -0
- package/table/cell.d.ts +15 -0
- package/table/coalesced-style-scheduler.d.ts +3 -0
- package/table/index.d.ts +5 -1
- package/table/package.json +6 -6
- package/table/row.d.ts +19 -0
- package/table/table-module.d.ts +9 -7
- package/table/table.d.ts +13 -0
- package/table/table_public_index.d.ts +4 -0
- package/table/text-column.d.ts +3 -0
- package/testing/package.json +5 -5
- package/testing/protractor/package.json +5 -5
- package/testing/selenium-webdriver/package.json +5 -5
- package/testing/testbed/package.json +5 -5
- package/testing/testbed/proxy-zone-types.d.ts +1 -1
- package/testing/testbed/zone-types.d.ts +1 -1
- package/text-field/autofill.d.ts +5 -0
- package/text-field/autosize.d.ts +3 -0
- package/text-field/index.d.ts +5 -1
- package/text-field/package.json +6 -6
- package/text-field/text-field-module.d.ts +7 -7
- package/text-field/text-field_public_index.d.ts +4 -0
- package/tree/control/base-tree-control.d.ts +1 -1
- package/tree/control/nested-tree-control.d.ts +2 -2
- package/tree/index.d.ts +5 -1
- package/tree/nested-node.d.ts +3 -0
- package/tree/node.d.ts +3 -0
- package/tree/outlet.d.ts +3 -0
- package/tree/package.json +6 -6
- package/tree/padding.d.ts +3 -0
- package/tree/toggle.d.ts +3 -0
- package/tree/tree-module.d.ts +10 -7
- package/tree/tree.d.ts +5 -0
- package/tree/tree_public_index.d.ts +4 -0
- package/a11y/index.metadata.json +0 -1
- package/accordion/index.metadata.json +0 -1
- package/bidi/index.metadata.json +0 -1
- package/bundles/cdk-a11y.umd.js +0 -2752
- package/bundles/cdk-a11y.umd.js.map +0 -1
- package/bundles/cdk-accordion.umd.js +0 -262
- package/bundles/cdk-accordion.umd.js.map +0 -1
- package/bundles/cdk-bidi.umd.js +0 -206
- package/bundles/cdk-bidi.umd.js.map +0 -1
- package/bundles/cdk-clipboard.umd.js +0 -278
- package/bundles/cdk-clipboard.umd.js.map +0 -1
- package/bundles/cdk-coercion.umd.js +0 -477
- package/bundles/cdk-coercion.umd.js.map +0 -1
- package/bundles/cdk-collections.umd.js +0 -846
- package/bundles/cdk-collections.umd.js.map +0 -1
- package/bundles/cdk-drag-drop.umd.js +0 -3921
- package/bundles/cdk-drag-drop.umd.js.map +0 -1
- package/bundles/cdk-keycodes.umd.js +0 -292
- package/bundles/cdk-keycodes.umd.js.map +0 -1
- package/bundles/cdk-layout.umd.js +0 -284
- package/bundles/cdk-layout.umd.js.map +0 -1
- package/bundles/cdk-observers.umd.js +0 -242
- package/bundles/cdk-observers.umd.js.map +0 -1
- package/bundles/cdk-overlay.umd.js +0 -3417
- package/bundles/cdk-overlay.umd.js.map +0 -1
- package/bundles/cdk-platform.umd.js +0 -397
- package/bundles/cdk-platform.umd.js.map +0 -1
- package/bundles/cdk-portal.umd.js +0 -1008
- package/bundles/cdk-portal.umd.js.map +0 -1
- package/bundles/cdk-scrolling.umd.js +0 -1787
- package/bundles/cdk-scrolling.umd.js.map +0 -1
- package/bundles/cdk-stepper.umd.js +0 -648
- package/bundles/cdk-stepper.umd.js.map +0 -1
- package/bundles/cdk-table.umd.js +0 -2730
- package/bundles/cdk-table.umd.js.map +0 -1
- package/bundles/cdk-testing-protractor.umd.js +0 -833
- package/bundles/cdk-testing-protractor.umd.js.map +0 -1
- package/bundles/cdk-testing-selenium-webdriver.umd.js +0 -1002
- package/bundles/cdk-testing-selenium-webdriver.umd.js.map +0 -1
- package/bundles/cdk-testing-testbed.umd.js +0 -1396
- package/bundles/cdk-testing-testbed.umd.js.map +0 -1
- package/bundles/cdk-testing.umd.js +0 -1285
- package/bundles/cdk-testing.umd.js.map +0 -1
- package/bundles/cdk-text-field.umd.js +0 -494
- package/bundles/cdk-text-field.umd.js.map +0 -1
- package/bundles/cdk-tree.umd.js +0 -1308
- package/bundles/cdk-tree.umd.js.map +0 -1
- package/bundles/cdk.umd.js +0 -38
- package/bundles/cdk.umd.js.map +0 -1
- package/clipboard/index.metadata.json +0 -1
- package/collections/index.metadata.json +0 -1
- package/drag-drop/index.metadata.json +0 -1
- package/esm2015/a11y/a11y-module.js +0 -30
- package/esm2015/a11y/a11y.externs.js +0 -6
- package/esm2015/a11y/aria-describer/aria-describer.js +0 -213
- package/esm2015/a11y/fake-event-detection.js +0 -28
- package/esm2015/a11y/focus-monitor/focus-monitor.js +0 -394
- package/esm2015/a11y/focus-trap/configurable-focus-trap-factory.js +0 -52
- package/esm2015/a11y/focus-trap/configurable-focus-trap.js +0 -49
- package/esm2015/a11y/focus-trap/event-listener-inert-strategy.js +0 -62
- package/esm2015/a11y/focus-trap/focus-trap-inert-strategy.js +0 -11
- package/esm2015/a11y/focus-trap/focus-trap-manager.js +0 -51
- package/esm2015/a11y/focus-trap/focus-trap.js +0 -391
- package/esm2015/a11y/high-contrast-mode/high-contrast-mode-detector.js +0 -92
- package/esm2015/a11y/index.js +0 -6
- package/esm2015/a11y/input-modality/input-modality-detector.js +0 -171
- package/esm2015/a11y/interactivity-checker/interactivity-checker.js +0 -237
- package/esm2015/a11y/key-manager/list-key-manager.js +0 -317
- package/esm2015/a11y/live-announcer/live-announcer-tokens.js +0 -19
- package/esm2015/a11y/live-announcer/live-announcer.js +0 -167
- package/esm2015/accordion/accordion-item.js +0 -146
- package/esm2015/accordion/accordion-module.js +0 -19
- package/esm2015/accordion/accordion.externs.js +0 -6
- package/esm2015/accordion/accordion.js +0 -63
- package/esm2015/accordion/index.js +0 -6
- package/esm2015/bidi/bidi-module.js +0 -18
- package/esm2015/bidi/bidi.externs.js +0 -6
- package/esm2015/bidi/dir.js +0 -58
- package/esm2015/bidi/directionality.js +0 -44
- package/esm2015/bidi/index.js +0 -6
- package/esm2015/cdk.externs.js +0 -0
- package/esm2015/clipboard/clipboard-module.js +0 -18
- package/esm2015/clipboard/clipboard.externs.js +0 -6
- package/esm2015/clipboard/clipboard.js +0 -52
- package/esm2015/clipboard/copy-to-clipboard.js +0 -90
- package/esm2015/clipboard/index.js +0 -5
- package/esm2015/clipboard/pending-copy.js +0 -68
- package/esm2015/coercion/coercion.externs.js +0 -0
- package/esm2015/collections/collection-viewer.js +0 -9
- package/esm2015/collections/collections.externs.js +0 -6
- package/esm2015/collections/dispose-view-repeater-strategy.js +0 -48
- package/esm2015/collections/index.js +0 -5
- package/esm2015/collections/recycle-view-repeater-strategy.js +0 -125
- package/esm2015/collections/tree-adapter.js +0 -9
- package/esm2015/collections/unique-selection-dispatcher.js +0 -53
- package/esm2015/collections/view-repeater.js +0 -14
- package/esm2015/drag-drop/client-rect.js +0 -60
- package/esm2015/drag-drop/clone-node.js +0 -65
- package/esm2015/drag-drop/directives/assertions.js +0 -19
- package/esm2015/drag-drop/directives/drag-handle.js +0 -57
- package/esm2015/drag-drop/directives/drag-placeholder.js +0 -36
- package/esm2015/drag-drop/directives/drag-preview.js +0 -42
- package/esm2015/drag-drop/directives/drag.js +0 -413
- package/esm2015/drag-drop/directives/drop-list-group.js +0 -47
- package/esm2015/drag-drop/directives/drop-list.js +0 -301
- package/esm2015/drag-drop/drag-drop-module.js +0 -43
- package/esm2015/drag-drop/drag-drop-registry.js +0 -231
- package/esm2015/drag-drop/drag-drop.externs.js +0 -6
- package/esm2015/drag-drop/drag-drop.js +0 -59
- package/esm2015/drag-drop/drag-events.js +0 -9
- package/esm2015/drag-drop/drag-ref.js +0 -1110
- package/esm2015/drag-drop/drag-styling.js +0 -69
- package/esm2015/drag-drop/drag-utils.js +0 -60
- package/esm2015/drag-drop/drop-list-ref.js +0 -813
- package/esm2015/drag-drop/index.js +0 -5
- package/esm2015/drag-drop/transition-duration.js +0 -36
- package/esm2015/keycodes/index.js +0 -5
- package/esm2015/keycodes/keycodes.externs.js +0 -6
- package/esm2015/layout/breakpoints-observer.js +0 -106
- package/esm2015/layout/index.js +0 -5
- package/esm2015/layout/layout-module.js +0 -14
- package/esm2015/layout/layout.externs.js +0 -6
- package/esm2015/layout/media-matcher.js +0 -85
- package/esm2015/observers/index.js +0 -5
- package/esm2015/observers/observe-content.js +0 -179
- package/esm2015/observers/observers.externs.js +0 -6
- package/esm2015/overlay/dispatchers/base-overlay-dispatcher.js +0 -51
- package/esm2015/overlay/dispatchers/overlay-keyboard-dispatcher.js +0 -62
- package/esm2015/overlay/dispatchers/overlay-outside-click-dispatcher.js +0 -97
- package/esm2015/overlay/fullscreen-overlay-container.js +0 -94
- package/esm2015/overlay/index.js +0 -7
- package/esm2015/overlay/overlay-config.js +0 -45
- package/esm2015/overlay/overlay-container.js +0 -85
- package/esm2015/overlay/overlay-directives.js +0 -352
- package/esm2015/overlay/overlay-module.js +0 -27
- package/esm2015/overlay/overlay-ref.js +0 -409
- package/esm2015/overlay/overlay.externs.js +0 -6
- package/esm2015/overlay/overlay.js +0 -119
- package/esm2015/overlay/position/connected-position.js +0 -94
- package/esm2015/overlay/position/flexible-connected-position-strategy.js +0 -960
- package/esm2015/overlay/position/global-position-strategy.js +0 -197
- package/esm2015/overlay/position/overlay-position-builder.js +0 -52
- package/esm2015/overlay/position/scroll-clip.js +0 -42
- package/esm2015/overlay/scroll/close-scroll-strategy.js +0 -61
- package/esm2015/overlay/scroll/scroll-strategy-options.js +0 -57
- package/esm2015/platform/features/passive-listeners.js +0 -36
- package/esm2015/platform/features/scrolling.js +0 -85
- package/esm2015/platform/features/test-environment.js +0 -16
- package/esm2015/platform/index.js +0 -5
- package/esm2015/platform/platform-module.js +0 -14
- package/esm2015/platform/platform.externs.js +0 -6
- package/esm2015/platform/platform.js +0 -77
- package/esm2015/portal/dom-portal-outlet.js +0 -136
- package/esm2015/portal/index.js +0 -5
- package/esm2015/portal/portal-directives.js +0 -221
- package/esm2015/portal/portal-injector.js +0 -28
- package/esm2015/portal/portal.externs.js +0 -6
- package/esm2015/portal/portal.js +0 -179
- package/esm2015/scrolling/fixed-size-virtual-scroll.js +0 -188
- package/esm2015/scrolling/index.js +0 -5
- package/esm2015/scrolling/scroll-dispatcher.js +0 -163
- package/esm2015/scrolling/scrollable.js +0 -173
- package/esm2015/scrolling/scrolling-module.js +0 -49
- package/esm2015/scrolling/scrolling.externs.js +0 -6
- package/esm2015/scrolling/viewport-ruler.js +0 -139
- package/esm2015/scrolling/virtual-for-of.js +0 -293
- package/esm2015/scrolling/virtual-scroll-strategy.js +0 -11
- package/esm2015/scrolling/virtual-scroll-viewport.js +0 -371
- package/esm2015/stepper/index.js +0 -5
- package/esm2015/stepper/step-header.js +0 -29
- package/esm2015/stepper/step-label.js +0 -22
- package/esm2015/stepper/stepper-button.js +0 -72
- package/esm2015/stepper/stepper-module.js +0 -37
- package/esm2015/stepper/stepper.externs.js +0 -6
- package/esm2015/stepper/stepper.js +0 -428
- package/esm2015/table/can-stick.js +0 -42
- package/esm2015/table/cell.js +0 -211
- package/esm2015/table/coalesced-style-scheduler.js +0 -89
- package/esm2015/table/index.js +0 -5
- package/esm2015/table/row.js +0 -244
- package/esm2015/table/sticky-position-listener.js +0 -11
- package/esm2015/table/sticky-styler.js +0 -336
- package/esm2015/table/table-module.js +0 -47
- package/esm2015/table/table.externs.js +0 -6
- package/esm2015/table/table.js +0 -987
- package/esm2015/table/text-column.js +0 -127
- package/esm2015/testing/change-detection.js +0 -110
- package/esm2015/testing/component-harness.js +0 -344
- package/esm2015/testing/harness-environment.js +0 -219
- package/esm2015/testing/protractor/protractor-element.js +0 -274
- package/esm2015/testing/protractor/protractor-harness-environment.js +0 -79
- package/esm2015/testing/protractor/protractor.externs.js +0 -0
- package/esm2015/testing/selenium-webdriver/selenium-web-driver-element.js +0 -241
- package/esm2015/testing/selenium-webdriver/selenium-web-driver-harness-environment.js +0 -97
- package/esm2015/testing/selenium-webdriver/selenium-webdriver.externs.js +0 -0
- package/esm2015/testing/test-element.js +0 -48
- package/esm2015/testing/testbed/fake-events/dispatch-events.js +0 -53
- package/esm2015/testing/testbed/fake-events/element-focus.js +0 -39
- package/esm2015/testing/testbed/fake-events/event-objects.js +0 -107
- package/esm2015/testing/testbed/fake-events/type-in-element.js +0 -79
- package/esm2015/testing/testbed/task-state-zone-interceptor.js +0 -82
- package/esm2015/testing/testbed/testbed-harness-environment.js +0 -173
- package/esm2015/testing/testbed/testbed.externs.js +0 -0
- package/esm2015/testing/testbed/unit-test-element.js +0 -266
- package/esm2015/testing/testing.externs.js +0 -0
- package/esm2015/testing/text-filtering.js +0 -23
- package/esm2015/text-field/autofill.js +0 -117
- package/esm2015/text-field/autosize.js +0 -293
- package/esm2015/text-field/index.js +0 -5
- package/esm2015/text-field/text-field-module.js +0 -21
- package/esm2015/text-field/text-field.externs.js +0 -6
- package/esm2015/tree/control/nested-tree-control.js +0 -59
- package/esm2015/tree/index.js +0 -5
- package/esm2015/tree/nested-node.js +0 -112
- package/esm2015/tree/node.js +0 -36
- package/esm2015/tree/outlet.js +0 -34
- package/esm2015/tree/padding.js +0 -119
- package/esm2015/tree/toggle.js +0 -46
- package/esm2015/tree/tree-module.js +0 -32
- package/esm2015/tree/tree.externs.js +0 -6
- package/esm2015/tree/tree.js +0 -345
- package/fesm2015/a11y.js.map +0 -1
- package/fesm2015/accordion.js.map +0 -1
- package/fesm2015/bidi.js.map +0 -1
- package/fesm2015/cdk.js.map +0 -1
- package/fesm2015/clipboard.js.map +0 -1
- package/fesm2015/coercion.js.map +0 -1
- package/fesm2015/collections.js.map +0 -1
- package/fesm2015/drag-drop.js.map +0 -1
- package/fesm2015/keycodes.js.map +0 -1
- package/fesm2015/layout.js.map +0 -1
- package/fesm2015/observers.js.map +0 -1
- package/fesm2015/overlay.js.map +0 -1
- package/fesm2015/platform.js.map +0 -1
- package/fesm2015/portal.js.map +0 -1
- package/fesm2015/scrolling.js.map +0 -1
- package/fesm2015/stepper.js.map +0 -1
- package/fesm2015/table.js.map +0 -1
- package/fesm2015/testing/protractor.js.map +0 -1
- package/fesm2015/testing/selenium-webdriver.js.map +0 -1
- package/fesm2015/testing/testbed.js.map +0 -1
- package/fesm2015/testing.js.map +0 -1
- package/fesm2015/text-field.js.map +0 -1
- package/fesm2015/tree.js.map +0 -1
- package/keycodes/index.metadata.json +0 -1
- package/layout/index.metadata.json +0 -1
- package/observers/index.metadata.json +0 -1
- package/overlay/index.metadata.json +0 -1
- package/platform/index.metadata.json +0 -1
- package/portal/index.metadata.json +0 -1
- package/scrolling/index.metadata.json +0 -1
- package/stepper/index.metadata.json +0 -1
- package/table/index.metadata.json +0 -1
- package/text-field/index.metadata.json +0 -1
- package/tree/index.metadata.json +0 -1
|
@@ -1,960 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright Google LLC All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
-
* found in the LICENSE file at https://angular.io/license
|
|
7
|
-
*/
|
|
8
|
-
import { ElementRef } from '@angular/core';
|
|
9
|
-
import { ConnectedOverlayPositionChange, validateHorizontalPosition, validateVerticalPosition, } from './connected-position';
|
|
10
|
-
import { Subscription, Subject } from 'rxjs';
|
|
11
|
-
import { isElementScrolledOutsideView, isElementClippedByScrolling } from './scroll-clip';
|
|
12
|
-
import { coerceCssPixelValue, coerceArray } from '@angular/cdk/coercion';
|
|
13
|
-
// TODO: refactor clipping detection into a separate thing (part of scrolling module)
|
|
14
|
-
// TODO: doesn't handle both flexible width and height when it has to scroll along both axis.
|
|
15
|
-
/** Class to be added to the overlay bounding box. */
|
|
16
|
-
const boundingBoxClass = 'cdk-overlay-connected-position-bounding-box';
|
|
17
|
-
/** Regex used to split a string on its CSS units. */
|
|
18
|
-
const cssUnitPattern = /([A-Za-z%]+)$/;
|
|
19
|
-
/**
|
|
20
|
-
* A strategy for positioning overlays. Using this strategy, an overlay is given an
|
|
21
|
-
* implicit position relative some origin element. The relative position is defined in terms of
|
|
22
|
-
* a point on the origin element that is connected to a point on the overlay element. For example,
|
|
23
|
-
* a basic dropdown is connecting the bottom-left corner of the origin to the top-left corner
|
|
24
|
-
* of the overlay.
|
|
25
|
-
*/
|
|
26
|
-
export class FlexibleConnectedPositionStrategy {
|
|
27
|
-
constructor(connectedTo, _viewportRuler, _document, _platform, _overlayContainer) {
|
|
28
|
-
this._viewportRuler = _viewportRuler;
|
|
29
|
-
this._document = _document;
|
|
30
|
-
this._platform = _platform;
|
|
31
|
-
this._overlayContainer = _overlayContainer;
|
|
32
|
-
/** Last size used for the bounding box. Used to avoid resizing the overlay after open. */
|
|
33
|
-
this._lastBoundingBoxSize = { width: 0, height: 0 };
|
|
34
|
-
/** Whether the overlay was pushed in a previous positioning. */
|
|
35
|
-
this._isPushed = false;
|
|
36
|
-
/** Whether the overlay can be pushed on-screen on the initial open. */
|
|
37
|
-
this._canPush = true;
|
|
38
|
-
/** Whether the overlay can grow via flexible width/height after the initial open. */
|
|
39
|
-
this._growAfterOpen = false;
|
|
40
|
-
/** Whether the overlay's width and height can be constrained to fit within the viewport. */
|
|
41
|
-
this._hasFlexibleDimensions = true;
|
|
42
|
-
/** Whether the overlay position is locked. */
|
|
43
|
-
this._positionLocked = false;
|
|
44
|
-
/** Amount of space that must be maintained between the overlay and the edge of the viewport. */
|
|
45
|
-
this._viewportMargin = 0;
|
|
46
|
-
/** The Scrollable containers used to check scrollable view properties on position change. */
|
|
47
|
-
this._scrollables = [];
|
|
48
|
-
/** Ordered list of preferred positions, from most to least desirable. */
|
|
49
|
-
this._preferredPositions = [];
|
|
50
|
-
/** Subject that emits whenever the position changes. */
|
|
51
|
-
this._positionChanges = new Subject();
|
|
52
|
-
/** Subscription to viewport size changes. */
|
|
53
|
-
this._resizeSubscription = Subscription.EMPTY;
|
|
54
|
-
/** Default offset for the overlay along the x axis. */
|
|
55
|
-
this._offsetX = 0;
|
|
56
|
-
/** Default offset for the overlay along the y axis. */
|
|
57
|
-
this._offsetY = 0;
|
|
58
|
-
/** Keeps track of the CSS classes that the position strategy has applied on the overlay panel. */
|
|
59
|
-
this._appliedPanelClasses = [];
|
|
60
|
-
/** Observable sequence of position changes. */
|
|
61
|
-
this.positionChanges = this._positionChanges;
|
|
62
|
-
this.setOrigin(connectedTo);
|
|
63
|
-
}
|
|
64
|
-
/** Ordered list of preferred positions, from most to least desirable. */
|
|
65
|
-
get positions() {
|
|
66
|
-
return this._preferredPositions;
|
|
67
|
-
}
|
|
68
|
-
/** Attaches this position strategy to an overlay. */
|
|
69
|
-
attach(overlayRef) {
|
|
70
|
-
if (this._overlayRef && overlayRef !== this._overlayRef &&
|
|
71
|
-
(typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
72
|
-
throw Error('This position strategy is already attached to an overlay');
|
|
73
|
-
}
|
|
74
|
-
this._validatePositions();
|
|
75
|
-
overlayRef.hostElement.classList.add(boundingBoxClass);
|
|
76
|
-
this._overlayRef = overlayRef;
|
|
77
|
-
this._boundingBox = overlayRef.hostElement;
|
|
78
|
-
this._pane = overlayRef.overlayElement;
|
|
79
|
-
this._isDisposed = false;
|
|
80
|
-
this._isInitialRender = true;
|
|
81
|
-
this._lastPosition = null;
|
|
82
|
-
this._resizeSubscription.unsubscribe();
|
|
83
|
-
this._resizeSubscription = this._viewportRuler.change().subscribe(() => {
|
|
84
|
-
// When the window is resized, we want to trigger the next reposition as if it
|
|
85
|
-
// was an initial render, in order for the strategy to pick a new optimal position,
|
|
86
|
-
// otherwise position locking will cause it to stay at the old one.
|
|
87
|
-
this._isInitialRender = true;
|
|
88
|
-
this.apply();
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Updates the position of the overlay element, using whichever preferred position relative
|
|
93
|
-
* to the origin best fits on-screen.
|
|
94
|
-
*
|
|
95
|
-
* The selection of a position goes as follows:
|
|
96
|
-
* - If any positions fit completely within the viewport as-is,
|
|
97
|
-
* choose the first position that does so.
|
|
98
|
-
* - If flexible dimensions are enabled and at least one satifies the given minimum width/height,
|
|
99
|
-
* choose the position with the greatest available size modified by the positions' weight.
|
|
100
|
-
* - If pushing is enabled, take the position that went off-screen the least and push it
|
|
101
|
-
* on-screen.
|
|
102
|
-
* - If none of the previous criteria were met, use the position that goes off-screen the least.
|
|
103
|
-
* @docs-private
|
|
104
|
-
*/
|
|
105
|
-
apply() {
|
|
106
|
-
// We shouldn't do anything if the strategy was disposed or we're on the server.
|
|
107
|
-
if (this._isDisposed || !this._platform.isBrowser) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
// If the position has been applied already (e.g. when the overlay was opened) and the
|
|
111
|
-
// consumer opted into locking in the position, re-use the old position, in order to
|
|
112
|
-
// prevent the overlay from jumping around.
|
|
113
|
-
if (!this._isInitialRender && this._positionLocked && this._lastPosition) {
|
|
114
|
-
this.reapplyLastPosition();
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
this._clearPanelClasses();
|
|
118
|
-
this._resetOverlayElementStyles();
|
|
119
|
-
this._resetBoundingBoxStyles();
|
|
120
|
-
// We need the bounding rects for the origin and the overlay to determine how to position
|
|
121
|
-
// the overlay relative to the origin.
|
|
122
|
-
// We use the viewport rect to determine whether a position would go off-screen.
|
|
123
|
-
this._viewportRect = this._getNarrowedViewportRect();
|
|
124
|
-
this._originRect = this._getOriginRect();
|
|
125
|
-
this._overlayRect = this._pane.getBoundingClientRect();
|
|
126
|
-
const originRect = this._originRect;
|
|
127
|
-
const overlayRect = this._overlayRect;
|
|
128
|
-
const viewportRect = this._viewportRect;
|
|
129
|
-
// Positions where the overlay will fit with flexible dimensions.
|
|
130
|
-
const flexibleFits = [];
|
|
131
|
-
// Fallback if none of the preferred positions fit within the viewport.
|
|
132
|
-
let fallback;
|
|
133
|
-
// Go through each of the preferred positions looking for a good fit.
|
|
134
|
-
// If a good fit is found, it will be applied immediately.
|
|
135
|
-
for (let pos of this._preferredPositions) {
|
|
136
|
-
// Get the exact (x, y) coordinate for the point-of-origin on the origin element.
|
|
137
|
-
let originPoint = this._getOriginPoint(originRect, pos);
|
|
138
|
-
// From that point-of-origin, get the exact (x, y) coordinate for the top-left corner of the
|
|
139
|
-
// overlay in this position. We use the top-left corner for calculations and later translate
|
|
140
|
-
// this into an appropriate (top, left, bottom, right) style.
|
|
141
|
-
let overlayPoint = this._getOverlayPoint(originPoint, overlayRect, pos);
|
|
142
|
-
// Calculate how well the overlay would fit into the viewport with this point.
|
|
143
|
-
let overlayFit = this._getOverlayFit(overlayPoint, overlayRect, viewportRect, pos);
|
|
144
|
-
// If the overlay, without any further work, fits into the viewport, use this position.
|
|
145
|
-
if (overlayFit.isCompletelyWithinViewport) {
|
|
146
|
-
this._isPushed = false;
|
|
147
|
-
this._applyPosition(pos, originPoint);
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
// If the overlay has flexible dimensions, we can use this position
|
|
151
|
-
// so long as there's enough space for the minimum dimensions.
|
|
152
|
-
if (this._canFitWithFlexibleDimensions(overlayFit, overlayPoint, viewportRect)) {
|
|
153
|
-
// Save positions where the overlay will fit with flexible dimensions. We will use these
|
|
154
|
-
// if none of the positions fit *without* flexible dimensions.
|
|
155
|
-
flexibleFits.push({
|
|
156
|
-
position: pos,
|
|
157
|
-
origin: originPoint,
|
|
158
|
-
overlayRect,
|
|
159
|
-
boundingBoxRect: this._calculateBoundingBoxRect(originPoint, pos)
|
|
160
|
-
});
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
// If the current preferred position does not fit on the screen, remember the position
|
|
164
|
-
// if it has more visible area on-screen than we've seen and move onto the next preferred
|
|
165
|
-
// position.
|
|
166
|
-
if (!fallback || fallback.overlayFit.visibleArea < overlayFit.visibleArea) {
|
|
167
|
-
fallback = { overlayFit, overlayPoint, originPoint, position: pos, overlayRect };
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
// If there are any positions where the overlay would fit with flexible dimensions, choose the
|
|
171
|
-
// one that has the greatest area available modified by the position's weight
|
|
172
|
-
if (flexibleFits.length) {
|
|
173
|
-
let bestFit = null;
|
|
174
|
-
let bestScore = -1;
|
|
175
|
-
for (const fit of flexibleFits) {
|
|
176
|
-
const score = fit.boundingBoxRect.width * fit.boundingBoxRect.height * (fit.position.weight || 1);
|
|
177
|
-
if (score > bestScore) {
|
|
178
|
-
bestScore = score;
|
|
179
|
-
bestFit = fit;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
this._isPushed = false;
|
|
183
|
-
this._applyPosition(bestFit.position, bestFit.origin);
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
// When none of the preferred positions fit within the viewport, take the position
|
|
187
|
-
// that went off-screen the least and attempt to push it on-screen.
|
|
188
|
-
if (this._canPush) {
|
|
189
|
-
// TODO(jelbourn): after pushing, the opening "direction" of the overlay might not make sense.
|
|
190
|
-
this._isPushed = true;
|
|
191
|
-
this._applyPosition(fallback.position, fallback.originPoint);
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
// All options for getting the overlay within the viewport have been exhausted, so go with the
|
|
195
|
-
// position that went off-screen the least.
|
|
196
|
-
this._applyPosition(fallback.position, fallback.originPoint);
|
|
197
|
-
}
|
|
198
|
-
detach() {
|
|
199
|
-
this._clearPanelClasses();
|
|
200
|
-
this._lastPosition = null;
|
|
201
|
-
this._previousPushAmount = null;
|
|
202
|
-
this._resizeSubscription.unsubscribe();
|
|
203
|
-
}
|
|
204
|
-
/** Cleanup after the element gets destroyed. */
|
|
205
|
-
dispose() {
|
|
206
|
-
if (this._isDisposed) {
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
// We can't use `_resetBoundingBoxStyles` here, because it resets
|
|
210
|
-
// some properties to zero, rather than removing them.
|
|
211
|
-
if (this._boundingBox) {
|
|
212
|
-
extendStyles(this._boundingBox.style, {
|
|
213
|
-
top: '',
|
|
214
|
-
left: '',
|
|
215
|
-
right: '',
|
|
216
|
-
bottom: '',
|
|
217
|
-
height: '',
|
|
218
|
-
width: '',
|
|
219
|
-
alignItems: '',
|
|
220
|
-
justifyContent: '',
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
if (this._pane) {
|
|
224
|
-
this._resetOverlayElementStyles();
|
|
225
|
-
}
|
|
226
|
-
if (this._overlayRef) {
|
|
227
|
-
this._overlayRef.hostElement.classList.remove(boundingBoxClass);
|
|
228
|
-
}
|
|
229
|
-
this.detach();
|
|
230
|
-
this._positionChanges.complete();
|
|
231
|
-
this._overlayRef = this._boundingBox = null;
|
|
232
|
-
this._isDisposed = true;
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* This re-aligns the overlay element with the trigger in its last calculated position,
|
|
236
|
-
* even if a position higher in the "preferred positions" list would now fit. This
|
|
237
|
-
* allows one to re-align the panel without changing the orientation of the panel.
|
|
238
|
-
*/
|
|
239
|
-
reapplyLastPosition() {
|
|
240
|
-
if (!this._isDisposed && (!this._platform || this._platform.isBrowser)) {
|
|
241
|
-
this._originRect = this._getOriginRect();
|
|
242
|
-
this._overlayRect = this._pane.getBoundingClientRect();
|
|
243
|
-
this._viewportRect = this._getNarrowedViewportRect();
|
|
244
|
-
const lastPosition = this._lastPosition || this._preferredPositions[0];
|
|
245
|
-
const originPoint = this._getOriginPoint(this._originRect, lastPosition);
|
|
246
|
-
this._applyPosition(lastPosition, originPoint);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Sets the list of Scrollable containers that host the origin element so that
|
|
251
|
-
* on reposition we can evaluate if it or the overlay has been clipped or outside view. Every
|
|
252
|
-
* Scrollable must be an ancestor element of the strategy's origin element.
|
|
253
|
-
*/
|
|
254
|
-
withScrollableContainers(scrollables) {
|
|
255
|
-
this._scrollables = scrollables;
|
|
256
|
-
return this;
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Adds new preferred positions.
|
|
260
|
-
* @param positions List of positions options for this overlay.
|
|
261
|
-
*/
|
|
262
|
-
withPositions(positions) {
|
|
263
|
-
this._preferredPositions = positions;
|
|
264
|
-
// If the last calculated position object isn't part of the positions anymore, clear
|
|
265
|
-
// it in order to avoid it being picked up if the consumer tries to re-apply.
|
|
266
|
-
if (positions.indexOf(this._lastPosition) === -1) {
|
|
267
|
-
this._lastPosition = null;
|
|
268
|
-
}
|
|
269
|
-
this._validatePositions();
|
|
270
|
-
return this;
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Sets a minimum distance the overlay may be positioned to the edge of the viewport.
|
|
274
|
-
* @param margin Required margin between the overlay and the viewport edge in pixels.
|
|
275
|
-
*/
|
|
276
|
-
withViewportMargin(margin) {
|
|
277
|
-
this._viewportMargin = margin;
|
|
278
|
-
return this;
|
|
279
|
-
}
|
|
280
|
-
/** Sets whether the overlay's width and height can be constrained to fit within the viewport. */
|
|
281
|
-
withFlexibleDimensions(flexibleDimensions = true) {
|
|
282
|
-
this._hasFlexibleDimensions = flexibleDimensions;
|
|
283
|
-
return this;
|
|
284
|
-
}
|
|
285
|
-
/** Sets whether the overlay can grow after the initial open via flexible width/height. */
|
|
286
|
-
withGrowAfterOpen(growAfterOpen = true) {
|
|
287
|
-
this._growAfterOpen = growAfterOpen;
|
|
288
|
-
return this;
|
|
289
|
-
}
|
|
290
|
-
/** Sets whether the overlay can be pushed on-screen if none of the provided positions fit. */
|
|
291
|
-
withPush(canPush = true) {
|
|
292
|
-
this._canPush = canPush;
|
|
293
|
-
return this;
|
|
294
|
-
}
|
|
295
|
-
/**
|
|
296
|
-
* Sets whether the overlay's position should be locked in after it is positioned
|
|
297
|
-
* initially. When an overlay is locked in, it won't attempt to reposition itself
|
|
298
|
-
* when the position is re-applied (e.g. when the user scrolls away).
|
|
299
|
-
* @param isLocked Whether the overlay should locked in.
|
|
300
|
-
*/
|
|
301
|
-
withLockedPosition(isLocked = true) {
|
|
302
|
-
this._positionLocked = isLocked;
|
|
303
|
-
return this;
|
|
304
|
-
}
|
|
305
|
-
/**
|
|
306
|
-
* Sets the origin, relative to which to position the overlay.
|
|
307
|
-
* Using an element origin is useful for building components that need to be positioned
|
|
308
|
-
* relatively to a trigger (e.g. dropdown menus or tooltips), whereas using a point can be
|
|
309
|
-
* used for cases like contextual menus which open relative to the user's pointer.
|
|
310
|
-
* @param origin Reference to the new origin.
|
|
311
|
-
*/
|
|
312
|
-
setOrigin(origin) {
|
|
313
|
-
this._origin = origin;
|
|
314
|
-
return this;
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* Sets the default offset for the overlay's connection point on the x-axis.
|
|
318
|
-
* @param offset New offset in the X axis.
|
|
319
|
-
*/
|
|
320
|
-
withDefaultOffsetX(offset) {
|
|
321
|
-
this._offsetX = offset;
|
|
322
|
-
return this;
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* Sets the default offset for the overlay's connection point on the y-axis.
|
|
326
|
-
* @param offset New offset in the Y axis.
|
|
327
|
-
*/
|
|
328
|
-
withDefaultOffsetY(offset) {
|
|
329
|
-
this._offsetY = offset;
|
|
330
|
-
return this;
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Configures that the position strategy should set a `transform-origin` on some elements
|
|
334
|
-
* inside the overlay, depending on the current position that is being applied. This is
|
|
335
|
-
* useful for the cases where the origin of an animation can change depending on the
|
|
336
|
-
* alignment of the overlay.
|
|
337
|
-
* @param selector CSS selector that will be used to find the target
|
|
338
|
-
* elements onto which to set the transform origin.
|
|
339
|
-
*/
|
|
340
|
-
withTransformOriginOn(selector) {
|
|
341
|
-
this._transformOriginSelector = selector;
|
|
342
|
-
return this;
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Gets the (x, y) coordinate of a connection point on the origin based on a relative position.
|
|
346
|
-
*/
|
|
347
|
-
_getOriginPoint(originRect, pos) {
|
|
348
|
-
let x;
|
|
349
|
-
if (pos.originX == 'center') {
|
|
350
|
-
// Note: when centering we should always use the `left`
|
|
351
|
-
// offset, otherwise the position will be wrong in RTL.
|
|
352
|
-
x = originRect.left + (originRect.width / 2);
|
|
353
|
-
}
|
|
354
|
-
else {
|
|
355
|
-
const startX = this._isRtl() ? originRect.right : originRect.left;
|
|
356
|
-
const endX = this._isRtl() ? originRect.left : originRect.right;
|
|
357
|
-
x = pos.originX == 'start' ? startX : endX;
|
|
358
|
-
}
|
|
359
|
-
let y;
|
|
360
|
-
if (pos.originY == 'center') {
|
|
361
|
-
y = originRect.top + (originRect.height / 2);
|
|
362
|
-
}
|
|
363
|
-
else {
|
|
364
|
-
y = pos.originY == 'top' ? originRect.top : originRect.bottom;
|
|
365
|
-
}
|
|
366
|
-
return { x, y };
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Gets the (x, y) coordinate of the top-left corner of the overlay given a given position and
|
|
370
|
-
* origin point to which the overlay should be connected.
|
|
371
|
-
*/
|
|
372
|
-
_getOverlayPoint(originPoint, overlayRect, pos) {
|
|
373
|
-
// Calculate the (overlayStartX, overlayStartY), the start of the
|
|
374
|
-
// potential overlay position relative to the origin point.
|
|
375
|
-
let overlayStartX;
|
|
376
|
-
if (pos.overlayX == 'center') {
|
|
377
|
-
overlayStartX = -overlayRect.width / 2;
|
|
378
|
-
}
|
|
379
|
-
else if (pos.overlayX === 'start') {
|
|
380
|
-
overlayStartX = this._isRtl() ? -overlayRect.width : 0;
|
|
381
|
-
}
|
|
382
|
-
else {
|
|
383
|
-
overlayStartX = this._isRtl() ? 0 : -overlayRect.width;
|
|
384
|
-
}
|
|
385
|
-
let overlayStartY;
|
|
386
|
-
if (pos.overlayY == 'center') {
|
|
387
|
-
overlayStartY = -overlayRect.height / 2;
|
|
388
|
-
}
|
|
389
|
-
else {
|
|
390
|
-
overlayStartY = pos.overlayY == 'top' ? 0 : -overlayRect.height;
|
|
391
|
-
}
|
|
392
|
-
// The (x, y) coordinates of the overlay.
|
|
393
|
-
return {
|
|
394
|
-
x: originPoint.x + overlayStartX,
|
|
395
|
-
y: originPoint.y + overlayStartY,
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
/** Gets how well an overlay at the given point will fit within the viewport. */
|
|
399
|
-
_getOverlayFit(point, rawOverlayRect, viewport, position) {
|
|
400
|
-
// Round the overlay rect when comparing against the
|
|
401
|
-
// viewport, because the viewport is always rounded.
|
|
402
|
-
const overlay = getRoundedBoundingClientRect(rawOverlayRect);
|
|
403
|
-
let { x, y } = point;
|
|
404
|
-
let offsetX = this._getOffset(position, 'x');
|
|
405
|
-
let offsetY = this._getOffset(position, 'y');
|
|
406
|
-
// Account for the offsets since they could push the overlay out of the viewport.
|
|
407
|
-
if (offsetX) {
|
|
408
|
-
x += offsetX;
|
|
409
|
-
}
|
|
410
|
-
if (offsetY) {
|
|
411
|
-
y += offsetY;
|
|
412
|
-
}
|
|
413
|
-
// How much the overlay would overflow at this position, on each side.
|
|
414
|
-
let leftOverflow = 0 - x;
|
|
415
|
-
let rightOverflow = (x + overlay.width) - viewport.width;
|
|
416
|
-
let topOverflow = 0 - y;
|
|
417
|
-
let bottomOverflow = (y + overlay.height) - viewport.height;
|
|
418
|
-
// Visible parts of the element on each axis.
|
|
419
|
-
let visibleWidth = this._subtractOverflows(overlay.width, leftOverflow, rightOverflow);
|
|
420
|
-
let visibleHeight = this._subtractOverflows(overlay.height, topOverflow, bottomOverflow);
|
|
421
|
-
let visibleArea = visibleWidth * visibleHeight;
|
|
422
|
-
return {
|
|
423
|
-
visibleArea,
|
|
424
|
-
isCompletelyWithinViewport: (overlay.width * overlay.height) === visibleArea,
|
|
425
|
-
fitsInViewportVertically: visibleHeight === overlay.height,
|
|
426
|
-
fitsInViewportHorizontally: visibleWidth == overlay.width,
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
/**
|
|
430
|
-
* Whether the overlay can fit within the viewport when it may resize either its width or height.
|
|
431
|
-
* @param fit How well the overlay fits in the viewport at some position.
|
|
432
|
-
* @param point The (x, y) coordinates of the overlat at some position.
|
|
433
|
-
* @param viewport The geometry of the viewport.
|
|
434
|
-
*/
|
|
435
|
-
_canFitWithFlexibleDimensions(fit, point, viewport) {
|
|
436
|
-
if (this._hasFlexibleDimensions) {
|
|
437
|
-
const availableHeight = viewport.bottom - point.y;
|
|
438
|
-
const availableWidth = viewport.right - point.x;
|
|
439
|
-
const minHeight = getPixelValue(this._overlayRef.getConfig().minHeight);
|
|
440
|
-
const minWidth = getPixelValue(this._overlayRef.getConfig().minWidth);
|
|
441
|
-
const verticalFit = fit.fitsInViewportVertically ||
|
|
442
|
-
(minHeight != null && minHeight <= availableHeight);
|
|
443
|
-
const horizontalFit = fit.fitsInViewportHorizontally ||
|
|
444
|
-
(minWidth != null && minWidth <= availableWidth);
|
|
445
|
-
return verticalFit && horizontalFit;
|
|
446
|
-
}
|
|
447
|
-
return false;
|
|
448
|
-
}
|
|
449
|
-
/**
|
|
450
|
-
* Gets the point at which the overlay can be "pushed" on-screen. If the overlay is larger than
|
|
451
|
-
* the viewport, the top-left corner will be pushed on-screen (with overflow occuring on the
|
|
452
|
-
* right and bottom).
|
|
453
|
-
*
|
|
454
|
-
* @param start Starting point from which the overlay is pushed.
|
|
455
|
-
* @param overlay Dimensions of the overlay.
|
|
456
|
-
* @param scrollPosition Current viewport scroll position.
|
|
457
|
-
* @returns The point at which to position the overlay after pushing. This is effectively a new
|
|
458
|
-
* originPoint.
|
|
459
|
-
*/
|
|
460
|
-
_pushOverlayOnScreen(start, rawOverlayRect, scrollPosition) {
|
|
461
|
-
// If the position is locked and we've pushed the overlay already, reuse the previous push
|
|
462
|
-
// amount, rather than pushing it again. If we were to continue pushing, the element would
|
|
463
|
-
// remain in the viewport, which goes against the expectations when position locking is enabled.
|
|
464
|
-
if (this._previousPushAmount && this._positionLocked) {
|
|
465
|
-
return {
|
|
466
|
-
x: start.x + this._previousPushAmount.x,
|
|
467
|
-
y: start.y + this._previousPushAmount.y
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
// Round the overlay rect when comparing against the
|
|
471
|
-
// viewport, because the viewport is always rounded.
|
|
472
|
-
const overlay = getRoundedBoundingClientRect(rawOverlayRect);
|
|
473
|
-
const viewport = this._viewportRect;
|
|
474
|
-
// Determine how much the overlay goes outside the viewport on each
|
|
475
|
-
// side, which we'll use to decide which direction to push it.
|
|
476
|
-
const overflowRight = Math.max(start.x + overlay.width - viewport.width, 0);
|
|
477
|
-
const overflowBottom = Math.max(start.y + overlay.height - viewport.height, 0);
|
|
478
|
-
const overflowTop = Math.max(viewport.top - scrollPosition.top - start.y, 0);
|
|
479
|
-
const overflowLeft = Math.max(viewport.left - scrollPosition.left - start.x, 0);
|
|
480
|
-
// Amount by which to push the overlay in each axis such that it remains on-screen.
|
|
481
|
-
let pushX = 0;
|
|
482
|
-
let pushY = 0;
|
|
483
|
-
// If the overlay fits completely within the bounds of the viewport, push it from whichever
|
|
484
|
-
// direction is goes off-screen. Otherwise, push the top-left corner such that its in the
|
|
485
|
-
// viewport and allow for the trailing end of the overlay to go out of bounds.
|
|
486
|
-
if (overlay.width <= viewport.width) {
|
|
487
|
-
pushX = overflowLeft || -overflowRight;
|
|
488
|
-
}
|
|
489
|
-
else {
|
|
490
|
-
pushX = start.x < this._viewportMargin ? (viewport.left - scrollPosition.left) - start.x : 0;
|
|
491
|
-
}
|
|
492
|
-
if (overlay.height <= viewport.height) {
|
|
493
|
-
pushY = overflowTop || -overflowBottom;
|
|
494
|
-
}
|
|
495
|
-
else {
|
|
496
|
-
pushY = start.y < this._viewportMargin ? (viewport.top - scrollPosition.top) - start.y : 0;
|
|
497
|
-
}
|
|
498
|
-
this._previousPushAmount = { x: pushX, y: pushY };
|
|
499
|
-
return {
|
|
500
|
-
x: start.x + pushX,
|
|
501
|
-
y: start.y + pushY,
|
|
502
|
-
};
|
|
503
|
-
}
|
|
504
|
-
/**
|
|
505
|
-
* Applies a computed position to the overlay and emits a position change.
|
|
506
|
-
* @param position The position preference
|
|
507
|
-
* @param originPoint The point on the origin element where the overlay is connected.
|
|
508
|
-
*/
|
|
509
|
-
_applyPosition(position, originPoint) {
|
|
510
|
-
this._setTransformOrigin(position);
|
|
511
|
-
this._setOverlayElementStyles(originPoint, position);
|
|
512
|
-
this._setBoundingBoxStyles(originPoint, position);
|
|
513
|
-
if (position.panelClass) {
|
|
514
|
-
this._addPanelClasses(position.panelClass);
|
|
515
|
-
}
|
|
516
|
-
// Save the last connected position in case the position needs to be re-calculated.
|
|
517
|
-
this._lastPosition = position;
|
|
518
|
-
// Notify that the position has been changed along with its change properties.
|
|
519
|
-
// We only emit if we've got any subscriptions, because the scroll visibility
|
|
520
|
-
// calculcations can be somewhat expensive.
|
|
521
|
-
if (this._positionChanges.observers.length) {
|
|
522
|
-
const scrollableViewProperties = this._getScrollVisibility();
|
|
523
|
-
const changeEvent = new ConnectedOverlayPositionChange(position, scrollableViewProperties);
|
|
524
|
-
this._positionChanges.next(changeEvent);
|
|
525
|
-
}
|
|
526
|
-
this._isInitialRender = false;
|
|
527
|
-
}
|
|
528
|
-
/** Sets the transform origin based on the configured selector and the passed-in position. */
|
|
529
|
-
_setTransformOrigin(position) {
|
|
530
|
-
if (!this._transformOriginSelector) {
|
|
531
|
-
return;
|
|
532
|
-
}
|
|
533
|
-
const elements = this._boundingBox.querySelectorAll(this._transformOriginSelector);
|
|
534
|
-
let xOrigin;
|
|
535
|
-
let yOrigin = position.overlayY;
|
|
536
|
-
if (position.overlayX === 'center') {
|
|
537
|
-
xOrigin = 'center';
|
|
538
|
-
}
|
|
539
|
-
else if (this._isRtl()) {
|
|
540
|
-
xOrigin = position.overlayX === 'start' ? 'right' : 'left';
|
|
541
|
-
}
|
|
542
|
-
else {
|
|
543
|
-
xOrigin = position.overlayX === 'start' ? 'left' : 'right';
|
|
544
|
-
}
|
|
545
|
-
for (let i = 0; i < elements.length; i++) {
|
|
546
|
-
elements[i].style.transformOrigin = `${xOrigin} ${yOrigin}`;
|
|
547
|
-
}
|
|
548
|
-
}
|
|
549
|
-
/**
|
|
550
|
-
* Gets the position and size of the overlay's sizing container.
|
|
551
|
-
*
|
|
552
|
-
* This method does no measuring and applies no styles so that we can cheaply compute the
|
|
553
|
-
* bounds for all positions and choose the best fit based on these results.
|
|
554
|
-
*/
|
|
555
|
-
_calculateBoundingBoxRect(origin, position) {
|
|
556
|
-
const viewport = this._viewportRect;
|
|
557
|
-
const isRtl = this._isRtl();
|
|
558
|
-
let height, top, bottom;
|
|
559
|
-
if (position.overlayY === 'top') {
|
|
560
|
-
// Overlay is opening "downward" and thus is bound by the bottom viewport edge.
|
|
561
|
-
top = origin.y;
|
|
562
|
-
height = viewport.height - top + this._viewportMargin;
|
|
563
|
-
}
|
|
564
|
-
else if (position.overlayY === 'bottom') {
|
|
565
|
-
// Overlay is opening "upward" and thus is bound by the top viewport edge. We need to add
|
|
566
|
-
// the viewport margin back in, because the viewport rect is narrowed down to remove the
|
|
567
|
-
// margin, whereas the `origin` position is calculated based on its `ClientRect`.
|
|
568
|
-
bottom = viewport.height - origin.y + this._viewportMargin * 2;
|
|
569
|
-
height = viewport.height - bottom + this._viewportMargin;
|
|
570
|
-
}
|
|
571
|
-
else {
|
|
572
|
-
// If neither top nor bottom, it means that the overlay is vertically centered on the
|
|
573
|
-
// origin point. Note that we want the position relative to the viewport, rather than
|
|
574
|
-
// the page, which is why we don't use something like `viewport.bottom - origin.y` and
|
|
575
|
-
// `origin.y - viewport.top`.
|
|
576
|
-
const smallestDistanceToViewportEdge = Math.min(viewport.bottom - origin.y + viewport.top, origin.y);
|
|
577
|
-
const previousHeight = this._lastBoundingBoxSize.height;
|
|
578
|
-
height = smallestDistanceToViewportEdge * 2;
|
|
579
|
-
top = origin.y - smallestDistanceToViewportEdge;
|
|
580
|
-
if (height > previousHeight && !this._isInitialRender && !this._growAfterOpen) {
|
|
581
|
-
top = origin.y - (previousHeight / 2);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
// The overlay is opening 'right-ward' (the content flows to the right).
|
|
585
|
-
const isBoundedByRightViewportEdge = (position.overlayX === 'start' && !isRtl) ||
|
|
586
|
-
(position.overlayX === 'end' && isRtl);
|
|
587
|
-
// The overlay is opening 'left-ward' (the content flows to the left).
|
|
588
|
-
const isBoundedByLeftViewportEdge = (position.overlayX === 'end' && !isRtl) ||
|
|
589
|
-
(position.overlayX === 'start' && isRtl);
|
|
590
|
-
let width, left, right;
|
|
591
|
-
if (isBoundedByLeftViewportEdge) {
|
|
592
|
-
right = viewport.width - origin.x + this._viewportMargin;
|
|
593
|
-
width = origin.x - this._viewportMargin;
|
|
594
|
-
}
|
|
595
|
-
else if (isBoundedByRightViewportEdge) {
|
|
596
|
-
left = origin.x;
|
|
597
|
-
width = viewport.right - origin.x;
|
|
598
|
-
}
|
|
599
|
-
else {
|
|
600
|
-
// If neither start nor end, it means that the overlay is horizontally centered on the
|
|
601
|
-
// origin point. Note that we want the position relative to the viewport, rather than
|
|
602
|
-
// the page, which is why we don't use something like `viewport.right - origin.x` and
|
|
603
|
-
// `origin.x - viewport.left`.
|
|
604
|
-
const smallestDistanceToViewportEdge = Math.min(viewport.right - origin.x + viewport.left, origin.x);
|
|
605
|
-
const previousWidth = this._lastBoundingBoxSize.width;
|
|
606
|
-
width = smallestDistanceToViewportEdge * 2;
|
|
607
|
-
left = origin.x - smallestDistanceToViewportEdge;
|
|
608
|
-
if (width > previousWidth && !this._isInitialRender && !this._growAfterOpen) {
|
|
609
|
-
left = origin.x - (previousWidth / 2);
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
return { top: top, left: left, bottom: bottom, right: right, width, height };
|
|
613
|
-
}
|
|
614
|
-
/**
|
|
615
|
-
* Sets the position and size of the overlay's sizing wrapper. The wrapper is positioned on the
|
|
616
|
-
* origin's connection point and stetches to the bounds of the viewport.
|
|
617
|
-
*
|
|
618
|
-
* @param origin The point on the origin element where the overlay is connected.
|
|
619
|
-
* @param position The position preference
|
|
620
|
-
*/
|
|
621
|
-
_setBoundingBoxStyles(origin, position) {
|
|
622
|
-
const boundingBoxRect = this._calculateBoundingBoxRect(origin, position);
|
|
623
|
-
// It's weird if the overlay *grows* while scrolling, so we take the last size into account
|
|
624
|
-
// when applying a new size.
|
|
625
|
-
if (!this._isInitialRender && !this._growAfterOpen) {
|
|
626
|
-
boundingBoxRect.height = Math.min(boundingBoxRect.height, this._lastBoundingBoxSize.height);
|
|
627
|
-
boundingBoxRect.width = Math.min(boundingBoxRect.width, this._lastBoundingBoxSize.width);
|
|
628
|
-
}
|
|
629
|
-
const styles = {};
|
|
630
|
-
if (this._hasExactPosition()) {
|
|
631
|
-
styles.top = styles.left = '0';
|
|
632
|
-
styles.bottom = styles.right = styles.maxHeight = styles.maxWidth = '';
|
|
633
|
-
styles.width = styles.height = '100%';
|
|
634
|
-
}
|
|
635
|
-
else {
|
|
636
|
-
const maxHeight = this._overlayRef.getConfig().maxHeight;
|
|
637
|
-
const maxWidth = this._overlayRef.getConfig().maxWidth;
|
|
638
|
-
styles.height = coerceCssPixelValue(boundingBoxRect.height);
|
|
639
|
-
styles.top = coerceCssPixelValue(boundingBoxRect.top);
|
|
640
|
-
styles.bottom = coerceCssPixelValue(boundingBoxRect.bottom);
|
|
641
|
-
styles.width = coerceCssPixelValue(boundingBoxRect.width);
|
|
642
|
-
styles.left = coerceCssPixelValue(boundingBoxRect.left);
|
|
643
|
-
styles.right = coerceCssPixelValue(boundingBoxRect.right);
|
|
644
|
-
// Push the pane content towards the proper direction.
|
|
645
|
-
if (position.overlayX === 'center') {
|
|
646
|
-
styles.alignItems = 'center';
|
|
647
|
-
}
|
|
648
|
-
else {
|
|
649
|
-
styles.alignItems = position.overlayX === 'end' ? 'flex-end' : 'flex-start';
|
|
650
|
-
}
|
|
651
|
-
if (position.overlayY === 'center') {
|
|
652
|
-
styles.justifyContent = 'center';
|
|
653
|
-
}
|
|
654
|
-
else {
|
|
655
|
-
styles.justifyContent = position.overlayY === 'bottom' ? 'flex-end' : 'flex-start';
|
|
656
|
-
}
|
|
657
|
-
if (maxHeight) {
|
|
658
|
-
styles.maxHeight = coerceCssPixelValue(maxHeight);
|
|
659
|
-
}
|
|
660
|
-
if (maxWidth) {
|
|
661
|
-
styles.maxWidth = coerceCssPixelValue(maxWidth);
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
this._lastBoundingBoxSize = boundingBoxRect;
|
|
665
|
-
extendStyles(this._boundingBox.style, styles);
|
|
666
|
-
}
|
|
667
|
-
/** Resets the styles for the bounding box so that a new positioning can be computed. */
|
|
668
|
-
_resetBoundingBoxStyles() {
|
|
669
|
-
extendStyles(this._boundingBox.style, {
|
|
670
|
-
top: '0',
|
|
671
|
-
left: '0',
|
|
672
|
-
right: '0',
|
|
673
|
-
bottom: '0',
|
|
674
|
-
height: '',
|
|
675
|
-
width: '',
|
|
676
|
-
alignItems: '',
|
|
677
|
-
justifyContent: '',
|
|
678
|
-
});
|
|
679
|
-
}
|
|
680
|
-
/** Resets the styles for the overlay pane so that a new positioning can be computed. */
|
|
681
|
-
_resetOverlayElementStyles() {
|
|
682
|
-
extendStyles(this._pane.style, {
|
|
683
|
-
top: '',
|
|
684
|
-
left: '',
|
|
685
|
-
bottom: '',
|
|
686
|
-
right: '',
|
|
687
|
-
position: '',
|
|
688
|
-
transform: '',
|
|
689
|
-
});
|
|
690
|
-
}
|
|
691
|
-
/** Sets positioning styles to the overlay element. */
|
|
692
|
-
_setOverlayElementStyles(originPoint, position) {
|
|
693
|
-
const styles = {};
|
|
694
|
-
const hasExactPosition = this._hasExactPosition();
|
|
695
|
-
const hasFlexibleDimensions = this._hasFlexibleDimensions;
|
|
696
|
-
const config = this._overlayRef.getConfig();
|
|
697
|
-
if (hasExactPosition) {
|
|
698
|
-
const scrollPosition = this._viewportRuler.getViewportScrollPosition();
|
|
699
|
-
extendStyles(styles, this._getExactOverlayY(position, originPoint, scrollPosition));
|
|
700
|
-
extendStyles(styles, this._getExactOverlayX(position, originPoint, scrollPosition));
|
|
701
|
-
}
|
|
702
|
-
else {
|
|
703
|
-
styles.position = 'static';
|
|
704
|
-
}
|
|
705
|
-
// Use a transform to apply the offsets. We do this because the `center` positions rely on
|
|
706
|
-
// being in the normal flex flow and setting a `top` / `left` at all will completely throw
|
|
707
|
-
// off the position. We also can't use margins, because they won't have an effect in some
|
|
708
|
-
// cases where the element doesn't have anything to "push off of". Finally, this works
|
|
709
|
-
// better both with flexible and non-flexible positioning.
|
|
710
|
-
let transformString = '';
|
|
711
|
-
let offsetX = this._getOffset(position, 'x');
|
|
712
|
-
let offsetY = this._getOffset(position, 'y');
|
|
713
|
-
if (offsetX) {
|
|
714
|
-
transformString += `translateX(${offsetX}px) `;
|
|
715
|
-
}
|
|
716
|
-
if (offsetY) {
|
|
717
|
-
transformString += `translateY(${offsetY}px)`;
|
|
718
|
-
}
|
|
719
|
-
styles.transform = transformString.trim();
|
|
720
|
-
// If a maxWidth or maxHeight is specified on the overlay, we remove them. We do this because
|
|
721
|
-
// we need these values to both be set to "100%" for the automatic flexible sizing to work.
|
|
722
|
-
// The maxHeight and maxWidth are set on the boundingBox in order to enforce the constraint.
|
|
723
|
-
// Note that this doesn't apply when we have an exact position, in which case we do want to
|
|
724
|
-
// apply them because they'll be cleared from the bounding box.
|
|
725
|
-
if (config.maxHeight) {
|
|
726
|
-
if (hasExactPosition) {
|
|
727
|
-
styles.maxHeight = coerceCssPixelValue(config.maxHeight);
|
|
728
|
-
}
|
|
729
|
-
else if (hasFlexibleDimensions) {
|
|
730
|
-
styles.maxHeight = '';
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
if (config.maxWidth) {
|
|
734
|
-
if (hasExactPosition) {
|
|
735
|
-
styles.maxWidth = coerceCssPixelValue(config.maxWidth);
|
|
736
|
-
}
|
|
737
|
-
else if (hasFlexibleDimensions) {
|
|
738
|
-
styles.maxWidth = '';
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
extendStyles(this._pane.style, styles);
|
|
742
|
-
}
|
|
743
|
-
/** Gets the exact top/bottom for the overlay when not using flexible sizing or when pushing. */
|
|
744
|
-
_getExactOverlayY(position, originPoint, scrollPosition) {
|
|
745
|
-
// Reset any existing styles. This is necessary in case the
|
|
746
|
-
// preferred position has changed since the last `apply`.
|
|
747
|
-
let styles = { top: '', bottom: '' };
|
|
748
|
-
let overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position);
|
|
749
|
-
if (this._isPushed) {
|
|
750
|
-
overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);
|
|
751
|
-
}
|
|
752
|
-
let virtualKeyboardOffset = this._overlayContainer.getContainerElement().getBoundingClientRect().top;
|
|
753
|
-
// Normally this would be zero, however when the overlay is attached to an input (e.g. in an
|
|
754
|
-
// autocomplete), mobile browsers will shift everything in order to put the input in the middle
|
|
755
|
-
// of the screen and to make space for the virtual keyboard. We need to account for this offset,
|
|
756
|
-
// otherwise our positioning will be thrown off.
|
|
757
|
-
overlayPoint.y -= virtualKeyboardOffset;
|
|
758
|
-
// We want to set either `top` or `bottom` based on whether the overlay wants to appear
|
|
759
|
-
// above or below the origin and the direction in which the element will expand.
|
|
760
|
-
if (position.overlayY === 'bottom') {
|
|
761
|
-
// When using `bottom`, we adjust the y position such that it is the distance
|
|
762
|
-
// from the bottom of the viewport rather than the top.
|
|
763
|
-
const documentHeight = this._document.documentElement.clientHeight;
|
|
764
|
-
styles.bottom = `${documentHeight - (overlayPoint.y + this._overlayRect.height)}px`;
|
|
765
|
-
}
|
|
766
|
-
else {
|
|
767
|
-
styles.top = coerceCssPixelValue(overlayPoint.y);
|
|
768
|
-
}
|
|
769
|
-
return styles;
|
|
770
|
-
}
|
|
771
|
-
/** Gets the exact left/right for the overlay when not using flexible sizing or when pushing. */
|
|
772
|
-
_getExactOverlayX(position, originPoint, scrollPosition) {
|
|
773
|
-
// Reset any existing styles. This is necessary in case the preferred position has
|
|
774
|
-
// changed since the last `apply`.
|
|
775
|
-
let styles = { left: '', right: '' };
|
|
776
|
-
let overlayPoint = this._getOverlayPoint(originPoint, this._overlayRect, position);
|
|
777
|
-
if (this._isPushed) {
|
|
778
|
-
overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);
|
|
779
|
-
}
|
|
780
|
-
// We want to set either `left` or `right` based on whether the overlay wants to appear "before"
|
|
781
|
-
// or "after" the origin, which determines the direction in which the element will expand.
|
|
782
|
-
// For the horizontal axis, the meaning of "before" and "after" change based on whether the
|
|
783
|
-
// page is in RTL or LTR.
|
|
784
|
-
let horizontalStyleProperty;
|
|
785
|
-
if (this._isRtl()) {
|
|
786
|
-
horizontalStyleProperty = position.overlayX === 'end' ? 'left' : 'right';
|
|
787
|
-
}
|
|
788
|
-
else {
|
|
789
|
-
horizontalStyleProperty = position.overlayX === 'end' ? 'right' : 'left';
|
|
790
|
-
}
|
|
791
|
-
// When we're setting `right`, we adjust the x position such that it is the distance
|
|
792
|
-
// from the right edge of the viewport rather than the left edge.
|
|
793
|
-
if (horizontalStyleProperty === 'right') {
|
|
794
|
-
const documentWidth = this._document.documentElement.clientWidth;
|
|
795
|
-
styles.right = `${documentWidth - (overlayPoint.x + this._overlayRect.width)}px`;
|
|
796
|
-
}
|
|
797
|
-
else {
|
|
798
|
-
styles.left = coerceCssPixelValue(overlayPoint.x);
|
|
799
|
-
}
|
|
800
|
-
return styles;
|
|
801
|
-
}
|
|
802
|
-
/**
|
|
803
|
-
* Gets the view properties of the trigger and overlay, including whether they are clipped
|
|
804
|
-
* or completely outside the view of any of the strategy's scrollables.
|
|
805
|
-
*/
|
|
806
|
-
_getScrollVisibility() {
|
|
807
|
-
// Note: needs fresh rects since the position could've changed.
|
|
808
|
-
const originBounds = this._getOriginRect();
|
|
809
|
-
const overlayBounds = this._pane.getBoundingClientRect();
|
|
810
|
-
// TODO(jelbourn): instead of needing all of the client rects for these scrolling containers
|
|
811
|
-
// every time, we should be able to use the scrollTop of the containers if the size of those
|
|
812
|
-
// containers hasn't changed.
|
|
813
|
-
const scrollContainerBounds = this._scrollables.map(scrollable => {
|
|
814
|
-
return scrollable.getElementRef().nativeElement.getBoundingClientRect();
|
|
815
|
-
});
|
|
816
|
-
return {
|
|
817
|
-
isOriginClipped: isElementClippedByScrolling(originBounds, scrollContainerBounds),
|
|
818
|
-
isOriginOutsideView: isElementScrolledOutsideView(originBounds, scrollContainerBounds),
|
|
819
|
-
isOverlayClipped: isElementClippedByScrolling(overlayBounds, scrollContainerBounds),
|
|
820
|
-
isOverlayOutsideView: isElementScrolledOutsideView(overlayBounds, scrollContainerBounds),
|
|
821
|
-
};
|
|
822
|
-
}
|
|
823
|
-
/** Subtracts the amount that an element is overflowing on an axis from its length. */
|
|
824
|
-
_subtractOverflows(length, ...overflows) {
|
|
825
|
-
return overflows.reduce((currentValue, currentOverflow) => {
|
|
826
|
-
return currentValue - Math.max(currentOverflow, 0);
|
|
827
|
-
}, length);
|
|
828
|
-
}
|
|
829
|
-
/** Narrows the given viewport rect by the current _viewportMargin. */
|
|
830
|
-
_getNarrowedViewportRect() {
|
|
831
|
-
// We recalculate the viewport rect here ourselves, rather than using the ViewportRuler,
|
|
832
|
-
// because we want to use the `clientWidth` and `clientHeight` as the base. The difference
|
|
833
|
-
// being that the client properties don't include the scrollbar, as opposed to `innerWidth`
|
|
834
|
-
// and `innerHeight` that do. This is necessary, because the overlay container uses
|
|
835
|
-
// 100% `width` and `height` which don't include the scrollbar either.
|
|
836
|
-
const width = this._document.documentElement.clientWidth;
|
|
837
|
-
const height = this._document.documentElement.clientHeight;
|
|
838
|
-
const scrollPosition = this._viewportRuler.getViewportScrollPosition();
|
|
839
|
-
return {
|
|
840
|
-
top: scrollPosition.top + this._viewportMargin,
|
|
841
|
-
left: scrollPosition.left + this._viewportMargin,
|
|
842
|
-
right: scrollPosition.left + width - this._viewportMargin,
|
|
843
|
-
bottom: scrollPosition.top + height - this._viewportMargin,
|
|
844
|
-
width: width - (2 * this._viewportMargin),
|
|
845
|
-
height: height - (2 * this._viewportMargin),
|
|
846
|
-
};
|
|
847
|
-
}
|
|
848
|
-
/** Whether the we're dealing with an RTL context */
|
|
849
|
-
_isRtl() {
|
|
850
|
-
return this._overlayRef.getDirection() === 'rtl';
|
|
851
|
-
}
|
|
852
|
-
/** Determines whether the overlay uses exact or flexible positioning. */
|
|
853
|
-
_hasExactPosition() {
|
|
854
|
-
return !this._hasFlexibleDimensions || this._isPushed;
|
|
855
|
-
}
|
|
856
|
-
/** Retrieves the offset of a position along the x or y axis. */
|
|
857
|
-
_getOffset(position, axis) {
|
|
858
|
-
if (axis === 'x') {
|
|
859
|
-
// We don't do something like `position['offset' + axis]` in
|
|
860
|
-
// order to avoid breking minifiers that rename properties.
|
|
861
|
-
return position.offsetX == null ? this._offsetX : position.offsetX;
|
|
862
|
-
}
|
|
863
|
-
return position.offsetY == null ? this._offsetY : position.offsetY;
|
|
864
|
-
}
|
|
865
|
-
/** Validates that the current position match the expected values. */
|
|
866
|
-
_validatePositions() {
|
|
867
|
-
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
868
|
-
if (!this._preferredPositions.length) {
|
|
869
|
-
throw Error('FlexibleConnectedPositionStrategy: At least one position is required.');
|
|
870
|
-
}
|
|
871
|
-
// TODO(crisbeto): remove these once Angular's template type
|
|
872
|
-
// checking is advanced enough to catch these cases.
|
|
873
|
-
this._preferredPositions.forEach(pair => {
|
|
874
|
-
validateHorizontalPosition('originX', pair.originX);
|
|
875
|
-
validateVerticalPosition('originY', pair.originY);
|
|
876
|
-
validateHorizontalPosition('overlayX', pair.overlayX);
|
|
877
|
-
validateVerticalPosition('overlayY', pair.overlayY);
|
|
878
|
-
});
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
/** Adds a single CSS class or an array of classes on the overlay panel. */
|
|
882
|
-
_addPanelClasses(cssClasses) {
|
|
883
|
-
if (this._pane) {
|
|
884
|
-
coerceArray(cssClasses).forEach(cssClass => {
|
|
885
|
-
if (cssClass !== '' && this._appliedPanelClasses.indexOf(cssClass) === -1) {
|
|
886
|
-
this._appliedPanelClasses.push(cssClass);
|
|
887
|
-
this._pane.classList.add(cssClass);
|
|
888
|
-
}
|
|
889
|
-
});
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
/** Clears the classes that the position strategy has applied from the overlay panel. */
|
|
893
|
-
_clearPanelClasses() {
|
|
894
|
-
if (this._pane) {
|
|
895
|
-
this._appliedPanelClasses.forEach(cssClass => {
|
|
896
|
-
this._pane.classList.remove(cssClass);
|
|
897
|
-
});
|
|
898
|
-
this._appliedPanelClasses = [];
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
/** Returns the ClientRect of the current origin. */
|
|
902
|
-
_getOriginRect() {
|
|
903
|
-
const origin = this._origin;
|
|
904
|
-
if (origin instanceof ElementRef) {
|
|
905
|
-
return origin.nativeElement.getBoundingClientRect();
|
|
906
|
-
}
|
|
907
|
-
// Check for Element so SVG elements are also supported.
|
|
908
|
-
if (origin instanceof Element) {
|
|
909
|
-
return origin.getBoundingClientRect();
|
|
910
|
-
}
|
|
911
|
-
const width = origin.width || 0;
|
|
912
|
-
const height = origin.height || 0;
|
|
913
|
-
// If the origin is a point, return a client rect as if it was a 0x0 element at the point.
|
|
914
|
-
return {
|
|
915
|
-
top: origin.y,
|
|
916
|
-
bottom: origin.y + height,
|
|
917
|
-
left: origin.x,
|
|
918
|
-
right: origin.x + width,
|
|
919
|
-
height,
|
|
920
|
-
width
|
|
921
|
-
};
|
|
922
|
-
}
|
|
923
|
-
}
|
|
924
|
-
/** Shallow-extends a stylesheet object with another stylesheet object. */
|
|
925
|
-
function extendStyles(destination, source) {
|
|
926
|
-
for (let key in source) {
|
|
927
|
-
if (source.hasOwnProperty(key)) {
|
|
928
|
-
destination[key] = source[key];
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
return destination;
|
|
932
|
-
}
|
|
933
|
-
/**
|
|
934
|
-
* Extracts the pixel value as a number from a value, if it's a number
|
|
935
|
-
* or a CSS pixel string (e.g. `1337px`). Otherwise returns null.
|
|
936
|
-
*/
|
|
937
|
-
function getPixelValue(input) {
|
|
938
|
-
if (typeof input !== 'number' && input != null) {
|
|
939
|
-
const [value, units] = input.split(cssUnitPattern);
|
|
940
|
-
return (!units || units === 'px') ? parseFloat(value) : null;
|
|
941
|
-
}
|
|
942
|
-
return input || null;
|
|
943
|
-
}
|
|
944
|
-
/**
|
|
945
|
-
* Gets a version of an element's bounding `ClientRect` where all the values are rounded down to
|
|
946
|
-
* the nearest pixel. This allows us to account for the cases where there may be sub-pixel
|
|
947
|
-
* deviations in the `ClientRect` returned by the browser (e.g. when zoomed in with a percentage
|
|
948
|
-
* size, see #21350).
|
|
949
|
-
*/
|
|
950
|
-
function getRoundedBoundingClientRect(clientRect) {
|
|
951
|
-
return {
|
|
952
|
-
top: Math.floor(clientRect.top),
|
|
953
|
-
right: Math.floor(clientRect.right),
|
|
954
|
-
bottom: Math.floor(clientRect.bottom),
|
|
955
|
-
left: Math.floor(clientRect.left),
|
|
956
|
-
width: Math.floor(clientRect.width),
|
|
957
|
-
height: Math.floor(clientRect.height)
|
|
958
|
-
};
|
|
959
|
-
}
|
|
960
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxleGlibGUtY29ubmVjdGVkLXBvc2l0aW9uLXN0cmF0ZWd5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2Nkay9vdmVybGF5L3Bvc2l0aW9uL2ZsZXhpYmxlLWNvbm5lY3RlZC1wb3NpdGlvbi1zdHJhdGVneS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFHSCxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBRXpDLE9BQU8sRUFDTCw4QkFBOEIsRUFHOUIsMEJBQTBCLEVBQzFCLHdCQUF3QixHQUN6QixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBYSxZQUFZLEVBQUUsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBRXZELE9BQU8sRUFBQyw0QkFBNEIsRUFBRSwyQkFBMkIsRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUN4RixPQUFPLEVBQUMsbUJBQW1CLEVBQUUsV0FBVyxFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFJdkUscUZBQXFGO0FBQ3JGLDZGQUE2RjtBQUU3RixxREFBcUQ7QUFDckQsTUFBTSxnQkFBZ0IsR0FBRyw2Q0FBNkMsQ0FBQztBQUV2RSxxREFBcUQ7QUFDckQsTUFBTSxjQUFjLEdBQUcsZUFBZSxDQUFDO0FBUXZDOzs7Ozs7R0FNRztBQUNILE1BQU0sT0FBTyxpQ0FBaUM7SUEwRjVDLFlBQ0ksV0FBb0QsRUFBVSxjQUE2QixFQUNuRixTQUFtQixFQUFVLFNBQW1CLEVBQ2hELGlCQUFtQztRQUZtQixtQkFBYyxHQUFkLGNBQWMsQ0FBZTtRQUNuRixjQUFTLEdBQVQsU0FBUyxDQUFVO1FBQVUsY0FBUyxHQUFULFNBQVMsQ0FBVTtRQUNoRCxzQkFBaUIsR0FBakIsaUJBQWlCLENBQWtCO1FBdEYvQywwRkFBMEY7UUFDbEYseUJBQW9CLEdBQUcsRUFBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUMsQ0FB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QUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7WUFDdkUsTUFBTSxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQztTQUN2QzthQUFNO1lBQ0wsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxTQUFTLENBQUM7WUFDekQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLENBQUM7WUFFdkQsTUFBTSxDQUFDLE1BQU0sR0FBRyxtQkFBbUIsQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDNUQsTUFBTSxDQUFDLEdBQUcsR0FBRyxtQkFBbUIsQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDdEQsTUFBTSxDQUFDLE1BQU0sR0FBRyxtQkFBbUIsQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDNUQsTUFBTSxDQUFDLEtBQUssR0FBRyxtQkFBbUIsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDMUQsTUFBTSxDQUFDLElBQUksR0FBRyxtQkFBbUIsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDeEQsTUFBTSxDQUFDLEtBQUssR0FBRyxtQkFBbUIsQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFMUQsc0RBQXNEO1lBQ3RELElBQUksUUFBUSxDQUFDLFFBQVEsS0FBSyxRQUFRLEVBQUU7Z0JBQ2xDLE1BQU0sQ0FBQyxVQUFVLEdBQUcsUUFBUSxDQUFDO2FBQzlCO2lCQUFNO2dCQUNMLE1BQU0sQ0FBQyxVQUFVLEdBQUcsUUFBUSxDQUFDLFFBQVEsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDO2FBQzdFO1lBRUQsSUFBSSxRQUFRLENBQUMsUUFBUSxLQUFLLFFBQVEs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QUFXLENBQUM7QUFDckIsQ0FBQztBQUdEOzs7R0FHRztBQUNILFNBQVMsYUFBYSxDQUFDLEtBQW1DO0lBQ3hELElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssSUFBSSxJQUFJLEVBQUU7UUFDOUMsTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ25ELE9BQU8sQ0FBQyxDQUFDLEtBQUssSUFBSSxLQUFLLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0tBQzlEO0lBRUQsT0FBTyxLQUFLLElBQUksSUFBSSxDQUFDO0FBQ3ZCLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsNEJBQTRCLENBQUMsVUFBc0I7SUFDMUQsT0FBTztRQUNMLEdBQUcsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUM7UUFDL0IsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQztRQUNuQyxNQUFNLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDO1FBQ3JDLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUM7UUFDakMsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQztRQUNuQyxNQUFNLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDO0tBQ3RDLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7UG9zaXRpb25TdHJhdGVneX0gZnJvbSAnLi9wb3NpdGlvbi1zdHJhdGVneSc7XG5pbXBvcnQge0VsZW1lbnRSZWZ9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtWaWV3cG9ydFJ1bGVyLCBDZGtTY3JvbGxhYmxlLCBWaWV3cG9ydFNjcm9sbFBvc2l0aW9ufSBmcm9tICdAYW5ndWxhci9jZGsvc2Nyb2xsaW5nJztcbmltcG9ydCB7XG4gIENvbm5lY3RlZE92ZXJsYXlQb3NpdGlvbkNoYW5nZSxcbiAgQ29ubmVjdGlvblBvc2l0aW9uUGFpcixcbiAgU2Nyb2xsaW5nVmlzaWJpbGl0eSxcbiAgdmFsaWRhdGVIb3Jpem9udGFsUG9zaXRpb24sXG4gIHZhbGlkYXRlVmVydGljYWxQb3NpdGlvbixcbn0gZnJvbSAnLi9jb25uZWN0ZWQtcG9zaXRpb24nO1xuaW1wb3J0IHtPYnNlcnZhYmxlLCBTdWJzY3JpcHRpb24sIFN1YmplY3R9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtPdmVybGF5UmVmZXJlbmNlfSBmcm9tICcuLi9vdmVybGF5LXJlZmVyZW5jZSc7XG5pbXBvcnQge2lzRWxlbWVudFNjcm9sbGVkT3V0c2lkZVZpZXcsIGlzRWxlbWVudENsaXBwZWRCeVNjcm9sbGluZ30gZnJvbSAnLi9zY3JvbGwtY2xpcCc7XG5pbXBvcnQge2NvZXJjZUNzc1BpeGVsVmFsdWUsIGNvZXJjZUFycmF5fSBmcm9tICdAYW5ndWxhci9jZGsvY29lcmNpb24nO1xuaW1wb3J0IHtQbGF0Zm9ybX0gZnJvbSAnQGFuZ3VsYXIvY2RrL3BsYXRmb3JtJztcbmltcG9ydCB7T3ZlcmxheUNvbnRhaW5lcn0gZnJvbSAnLi4vb3ZlcmxheS1jb250YWluZXInO1xuXG4vLyBUT0RPOiByZWZhY3RvciBjbGlwcGluZyBkZXRlY3Rpb24gaW50byBhIHNlcGFyYXRlIHRoaW5nIChwYXJ0IG9mIHNjcm9sbGluZyBtb2R1bGUpXG4vLyBUT0RPOiBkb2Vzbid0IGhhbmRsZSBib3RoIGZsZXhpYmxlIHdpZHRoIGFuZCBoZWlnaHQgd2hlbiBpdCBoYXMgdG8gc2Nyb2xsIGFsb25nIGJvdGggYXhpcy5cblxuLyoqIENsYXNzIHRvIGJlIGFkZGVkIHRvIHRoZSBvdmVybGF5IGJvdW5kaW5nIGJveC4gKi9cbmNvbnN0IGJvdW5kaW5nQm94Q2xhc3MgPSAnY2RrLW92ZXJsYXktY29ubmVjdGVkLXBvc2l0aW9uLWJvdW5kaW5nLWJveCc7XG5cbi8qKiBSZWdleCB1c2VkIHRvIHNwbGl0IGEgc3RyaW5nIG9uIGl0cyBDU1MgdW5pdHMuICovXG5jb25zdCBjc3NVbml0UGF0dGVybiA9IC8oW0EtWmEteiVdKykkLztcblxuLyoqIFBvc3NpYmxlIHZhbHVlcyB0aGF0IGNhbiBiZSBzZXQgYXMgdGhlIG9yaWdpbiBvZiBhIEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneS4gKi9cbmV4cG9ydCB0eXBlIEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneU9yaWdpbiA9IEVsZW1lbnRSZWYgfCBFbGVtZW50IHwgUG9pbnQgJiB7XG4gIHdpZHRoPzogbnVtYmVyO1xuICBoZWlnaHQ/OiBudW1iZXI7XG59O1xuXG4vKipcbiAqIEEgc3RyYXRlZ3kgZm9yIHBvc2l0aW9uaW5nIG92ZXJsYXlzLiBVc2luZyB0aGlzIHN0cmF0ZWd5LCBhbiBvdmVybGF5IGlzIGdpdmVuIGFuXG4gKiBpbXBsaWNpdCBwb3NpdGlvbiByZWxhdGl2ZSBzb21lIG9yaWdpbiBlbGVtZW50LiBUaGUgcmVsYXRpdmUgcG9zaXRpb24gaXMgZGVmaW5lZCBpbiB0ZXJtcyBvZlxuICogYSBwb2ludCBvbiB0aGUgb3JpZ2luIGVsZW1lbnQgdGhhdCBpcyBjb25uZWN0ZWQgdG8gYSBwb2ludCBvbiB0aGUgb3ZlcmxheSBlbGVtZW50LiBGb3IgZXhhbXBsZSxcbiAqIGEgYmFzaWMgZHJvcGRvd24gaXMgY29ubmVjdGluZyB0aGUgYm90dG9tLWxlZnQgY29ybmVyIG9mIHRoZSBvcmlnaW4gdG8gdGhlIHRvcC1sZWZ0IGNvcm5lclxuICogb2YgdGhlIG92ZXJsYXkuXG4gKi9cbmV4cG9ydCBjbGFzcyBGbGV4aWJsZUNvbm5lY3RlZFBvc2l0aW9uU3RyYXRlZ3kgaW1wbGVtZW50cyBQb3NpdGlvblN0cmF0ZWd5IHtcbiAgLyoqIFRoZSBvdmVybGF5IHRvIHdoaWNoIHRoaXMgc3RyYXRlZ3kgaXMgYXR0YWNoZWQuICovXG4gIHByaXZhdGUgX292ZXJsYXlSZWY6IE92ZXJsYXlSZWZlcmVuY2U7XG5cbiAgLyoqIFdoZXRoZXIgd2UncmUgcGVyZm9ybWluZyB0aGUgdmVyeSBmaXJzdCBwb3NpdGlvbmluZyBvZiB0aGUgb3ZlcmxheS4gKi9cbiAgcHJpdmF0ZSBfaXNJbml0aWFsUmVuZGVyOiBib29sZWFuO1xuXG4gIC8qKiBMYXN0IHNpemUgdXNlZCBmb3IgdGhlIGJvdW5kaW5nIGJveC4gVXNlZCB0byBhdm9pZCByZXNpemluZyB0aGUgb3ZlcmxheSBhZnRlciBvcGVuLiAqL1xuICBwcml2YXRlIF9sYXN0Qm91bmRpbmdCb3hTaXplID0ge3dpZHRoOiAwLCBoZWlnaHQ6IDB9O1xuXG4gIC8qKiBXaGV0aGVyIHRoZSBvdmVybGF5IHdhcyBwdXNoZWQgaW4gYSBwcmV2aW91cyBwb3NpdGlvbmluZy4gKi9cbiAgcHJpdmF0ZSBfaXNQdXNoZWQgPSBmYWxzZTtcblxuICAvKiogV2hldGhlciB0aGUgb3ZlcmxheSBjYW4gYmUgcHVzaGVkIG9uLXNjcmVlbiBvbiB0aGUgaW5pdGlhbCBvcGVuLiAqL1xuICBwcml2YXRlIF9jYW5QdXNoID0gdHJ1ZTtcblxuICAvKiogV2hldGhlciB0aGUgb3ZlcmxheSBjYW4gZ3JvdyB2aWEgZmxleGlibGUgd2lkdGgvaGVpZ2h0IGFmdGVyIHRoZSBpbml0aWFsIG9wZW4uICovXG4gIHByaXZhdGUgX2dyb3dBZnRlck9wZW4gPSBmYWxzZTtcblxuICAvKiogV2hldGhlciB0aGUgb3ZlcmxheSdzIHdpZHRoIGFuZCBoZWlnaHQgY2FuIGJlIGNvbnN0cmFpbmVkIHRvIGZpdCB3aXRoaW4gdGhlIHZpZXdwb3J0LiAqL1xuICBwcml2YXRlIF9oYXNGbGV4aWJsZURpbWVuc2lvbnMgPSB0cnVlO1xuXG4gIC8qKiBXaGV0aGVyIHRoZSBvdmVybGF5IHBvc2l0aW9uIGlzIGxvY2tlZC4gKi9cbiAgcHJpdmF0ZSBfcG9zaXRpb25Mb2NrZWQgPSBmYWxzZTtcblxuICAvKiogQ2FjaGVkIG9yaWdpbiBkaW1lbnNpb25zICovXG4gIHByaXZhdGUgX29yaWdpblJlY3Q6IENsaWVudFJlY3Q7XG5cbiAgLyoqIENhY2hlZCBvdmVybGF5IGRpbWVuc2lvbnMgKi9cbiAgcHJpdmF0ZSBfb3ZlcmxheVJlY3Q6IENsaWVudFJlY3Q7XG5cbiAgLyoqIENhY2hlZCB2aWV3cG9ydCBkaW1lbnNpb25zICovXG4gIHByaXZhdGUgX3ZpZXdwb3J0UmVjdDogQ2xpZW50UmVjdDtcblxuICAvKiogQW1vdW50IG9mIHNwYWNlIHRoYXQgbXVzdCBiZSBtYWludGFpbmVkIGJldHdlZW4gdGhlIG92ZXJsYXkgYW5kIHRoZSBlZGdlIG9mIHRoZSB2aWV3cG9ydC4gKi9cbiAgcHJpdmF0ZSBfdmlld3BvcnRNYXJnaW4gPSAwO1xuXG4gIC8qKiBUaGUgU2Nyb2xsYWJsZSBjb250YWluZXJzIHVzZWQgdG8gY2hlY2sgc2Nyb2xsYWJsZSB2aWV3IHByb3BlcnRpZXMgb24gcG9zaXRpb24gY2hhbmdlLiAqL1xuICBwcml2YXRlIF9zY3JvbGxhYmxlczogQ2RrU2Nyb2xsYWJsZVtdID0gW107XG5cbiAgLyoqIE9yZGVyZWQgbGlzdCBvZiBwcmVmZXJyZWQgcG9zaXRpb25zLCBmcm9tIG1vc3QgdG8gbGVhc3QgZGVzaXJhYmxlLiAqL1xuICBfcHJlZmVycmVkUG9zaXRpb25zOiBDb25uZWN0aW9uUG9zaXRpb25QYWlyW10gPSBbXTtcblxuICAvKiogVGhlIG9yaWdpbiBlbGVtZW50IGFnYWluc3Qgd2hpY2ggdGhlIG92ZXJsYXkgd2lsbCBiZSBwb3NpdGlvbmVkLiAqL1xuICBwcml2YXRlIF9vcmlnaW46IEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneU9yaWdpbjtcblxuICAvKiogVGhlIG92ZXJsYXkgcGFuZSBlbGVtZW50LiAqL1xuICBwcml2YXRlIF9wYW5lOiBIVE1MRWxlbWVudDtcblxuICAvKiogV2hldGhlciB0aGUgc3RyYXRlZ3kgaGFzIGJlZW4gZGlzcG9zZWQgb2YgYWxyZWFkeS4gKi9cbiAgcHJpdmF0ZSBfaXNEaXNwb3NlZDogYm9vbGVhbjtcblxuICAvKipcbiAgICogUGFyZW50IGVsZW1lbnQgZm9yIHRoZSBvdmVybGF5IHBhbmVsIHVzZWQgdG8gY29uc3RyYWluIHRoZSBvdmVybGF5IHBhbmVsJ3Mgc2l6ZSB0byBmaXRcbiAgICogd2l0aGluIHRoZSB2aWV3cG9ydC5cbiAgICovXG4gIHByaXZhdGUgX2JvdW5kaW5nQm94OiBIVE1MRWxlbWVudCB8IG51bGw7XG5cbiAgLyoqIFRoZSBsYXN0IHBvc2l0aW9uIHRvIGhhdmUgYmVlbiBjYWxjdWxhdGVkIGFzIHRoZSBiZXN0IGZpdCBwb3NpdGlvbi4gKi9cbiAgcHJpdmF0ZSBfbGFzdFBvc2l0aW9uOiBDb25uZWN0ZWRQb3NpdGlvbiB8IG51bGw7XG5cbiAgLyoqIFN1YmplY3QgdGhhdCBlbWl0cyB3aGVuZXZlciB0aGUgcG9zaXRpb24gY2hhbmdlcy4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBfcG9zaXRpb25DaGFuZ2VzID0gbmV3IFN1YmplY3Q8Q29ubmVjdGVkT3ZlcmxheVBvc2l0aW9uQ2hhbmdlPigpO1xuXG4gIC8qKiBTdWJzY3JpcHRpb24gdG8gdmlld3BvcnQgc2l6ZSBjaGFuZ2VzLiAqL1xuICBwcml2YXRlIF9yZXNpemVTdWJzY3JpcHRpb24gPSBTdWJzY3JpcHRpb24uRU1QVFk7XG5cbiAgLyoqIERlZmF1bHQgb2Zmc2V0IGZvciB0aGUgb3ZlcmxheSBhbG9uZyB0aGUgeCBheGlzLiAqL1xuICBwcml2YXRlIF9vZmZzZXRYID0gMDtcblxuICAvKiogRGVmYXVsdCBvZmZzZXQgZm9yIHRoZSBvdmVybGF5IGFsb25nIHRoZSB5IGF4aXMuICovXG4gIHByaXZhdGUgX29mZnNldFkgPSAwO1xuXG4gIC8qKiBTZWxlY3RvciB0byBiZSB1c2VkIHdoZW4gZmluZGluZyB0aGUgZWxlbWVudHMgb24gd2hpY2ggdG8gc2V0IHRoZSB0cmFuc2Zvcm0gb3JpZ2luLiAqL1xuICBwcml2YXRlIF90cmFuc2Zvcm1PcmlnaW5TZWxlY3Rvcjogc3RyaW5nO1xuXG4gIC8qKiBLZWVwcyB0cmFjayBvZiB0aGUgQ1NTIGNsYXNzZXMgdGhhdCB0aGUgcG9zaXRpb24gc3RyYXRlZ3kgaGFzIGFwcGxpZWQgb24gdGhlIG92ZXJsYXkgcGFuZWwuICovXG4gIHByaXZhdGUgX2FwcGxpZWRQYW5lbENsYXNzZXM6IHN0cmluZ1tdID0gW107XG5cbiAgLyoqIEFtb3VudCBieSB3aGljaCB0aGUgb3ZlcmxheSB3YXMgcHVzaGVkIGluIGVhY2ggYXhpcyBkdXJpbmcgdGhlIGxhc3QgdGltZSBpdCB3YXMgcG9zaXRpb25lZC4gKi9cbiAgcHJpdmF0ZSBfcHJldmlvdXNQdXNoQW1vdW50OiB7eDogbnVtYmVyLCB5OiBudW1iZXJ9IHwgbnVsbDtcblxuICAvKiogT2JzZXJ2YWJsZSBzZXF1ZW5jZSBvZiBwb3NpdGlvbiBjaGFuZ2VzLiAqL1xuICBwb3NpdGlvbkNoYW5nZXM6IE9ic2VydmFibGU8Q29ubmVjdGVkT3ZlcmxheVBvc2l0aW9uQ2hhbmdlPiA9IHRoaXMuX3Bvc2l0aW9uQ2hhbmdlcztcblxuICAvKiogT3JkZXJlZCBsaXN0IG9mIHByZWZlcnJlZCBwb3NpdGlvbnMsIGZyb20gbW9zdCB0byBsZWFzdCBkZXNpcmFibGUuICovXG4gIGdldCBwb3NpdGlvbnMoKTogQ29ubmVjdGlvblBvc2l0aW9uUGFpcltdIHtcbiAgICByZXR1cm4gdGhpcy5fcHJlZmVycmVkUG9zaXRpb25zO1xuICB9XG5cbiAgY29uc3RydWN0b3IoXG4gICAgICBjb25uZWN0ZWRUbzogRmxleGlibGVDb25uZWN0ZWRQb3NpdGlvblN0cmF0ZWd5T3JpZ2luLCBwcml2YXRlIF92aWV3cG9ydFJ1bGVyOiBWaWV3cG9ydFJ1bGVyLFxuICAgICAgcHJpdmF0ZSBfZG9jdW1lbnQ6IERvY3VtZW50LCBwcml2YXRlIF9wbGF0Zm9ybTogUGxhdGZvcm0sXG4gICAgICBwcml2YXRlIF9vdmVybGF5Q29udGFpbmVyOiBPdmVybGF5Q29udGFpbmVyKSB7XG4gICAgdGhpcy5zZXRPcmlnaW4oY29ubmVjdGVkVG8pO1xuICB9XG5cbiAgLyoqIEF0dGFjaGVzIHRoaXMgcG9zaXRpb24gc3RyYXRlZ3kgdG8gYW4gb3ZlcmxheS4gKi9cbiAgYXR0YWNoKG92ZXJsYXlSZWY6IE92ZXJsYXlSZWZlcmVuY2UpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fb3ZlcmxheVJlZiAmJiBvdmVybGF5UmVmICE9PSB0aGlzLl9vdmVybGF5UmVmICYmXG4gICAgICAodHlwZW9mIG5nRGV2TW9kZSA9PT0gJ3VuZGVmaW5lZCcgfHwgbmdEZXZNb2RlKSkge1xuICAgICAgdGhyb3cgRXJyb3IoJ1RoaXMgcG9zaXRpb24gc3RyYXRlZ3kgaXMgYWxyZWFkeSBhdHRhY2hlZCB0byBhbiBvdmVybGF5Jyk7XG4gICAgfVxuXG4gICAgdGhpcy5fdmFsaWRhdGVQb3NpdGlvbnMoKTtcblxuICAgIG92ZXJsYXlSZWYuaG9zdEVsZW1lbnQuY2xhc3NMaXN0LmFkZChib3VuZGluZ0JveENsYXNzKTtcblxuICAgIHRoaXMuX292ZXJsYXlSZWYgPSBvdmVybGF5UmVmO1xuICAgIHRoaXMuX2JvdW5kaW5nQm94ID0gb3ZlcmxheVJlZi5ob3N0RWxlbWVudDtcbiAgICB0aGlzLl9wYW5lID0gb3ZlcmxheVJlZi5vdmVybGF5RWxlbWVudDtcbiAgICB0aGlzLl9pc0Rpc3Bvc2VkID0gZmFsc2U7XG4gICAgdGhpcy5faXNJbml0aWFsUmVuZGVyID0gdHJ1ZTtcbiAgICB0aGlzLl9sYXN0UG9zaXRpb24gPSBudWxsO1xuICAgIHRoaXMuX3Jlc2l6ZVN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuX3Jlc2l6ZVN1YnNjcmlwdGlvbiA9IHRoaXMuX3ZpZXdwb3J0UnVsZXIuY2hhbmdlKCkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgIC8vIFdoZW4gdGhlIHdpbmRvdyBpcyByZXNpemVkLCB3ZSB3YW50IHRvIHRyaWdnZXIgdGhlIG5leHQgcmVwb3NpdGlvbiBhcyBpZiBpdFxuICAgICAgLy8gd2FzIGFuIGluaXRpYWwgcmVuZGVyLCBpbiBvcmRlciBmb3IgdGhlIHN0cmF0ZWd5IHRvIHBpY2sgYSBuZXcgb3B0aW1hbCBwb3NpdGlvbixcbiAgICAgIC8vIG90aGVyd2lzZSBwb3NpdGlvbiBsb2NraW5nIHdpbGwgY2F1c2UgaXQgdG8gc3RheSBhdCB0aGUgb2xkIG9uZS5cbiAgICAgIHRoaXMuX2lzSW5pdGlhbFJlbmRlciA9IHRydWU7XG4gICAgICB0aGlzLmFwcGx5KCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgcG9zaXRpb24gb2YgdGhlIG92ZXJsYXkgZWxlbWVudCwgdXNpbmcgd2hpY2hldmVyIHByZWZlcnJlZCBwb3NpdGlvbiByZWxhdGl2ZVxuICAgKiB0byB0aGUgb3JpZ2luIGJlc3QgZml0cyBvbi1zY3JlZW4uXG4gICAqXG4gICAqIFRoZSBzZWxlY3Rpb24gb2YgYSBwb3NpdGlvbiBnb2VzIGFzIGZvbGxvd3M6XG4gICAqICAtIElmIGFueSBwb3NpdGlvbnMgZml0IGNvbXBsZXRlbHkgd2l0aGluIHRoZSB2aWV3cG9ydCBhcy1pcyxcbiAgICogICAgICBjaG9vc2UgdGhlIGZpcnN0IHBvc2l0aW9uIHRoYXQgZG9lcyBzby5cbiAgICogIC0gSWYgZmxleGlibGUgZGltZW5zaW9ucyBhcmUgZW5hYmxlZCBhbmQgYXQgbGVhc3Qgb25lIHNhdGlmaWVzIHRoZSBnaXZlbiBtaW5pbXVtIHdpZHRoL2hlaWdodCxcbiAgICogICAgICBjaG9vc2UgdGhlIHBvc2l0aW9uIHdpdGggdGhlIGdyZWF0ZXN0IGF2YWlsYWJsZSBzaXplIG1vZGlmaWVkIGJ5IHRoZSBwb3NpdGlvbnMnIHdlaWdodC5cbiAgICogIC0gSWYgcHVzaGluZyBpcyBlbmFibGVkLCB0YWtlIHRoZSBwb3NpdGlvbiB0aGF0IHdlbnQgb2ZmLXNjcmVlbiB0aGUgbGVhc3QgYW5kIHB1c2ggaXRcbiAgICogICAgICBvbi1zY3JlZW4uXG4gICAqICAtIElmIG5vbmUgb2YgdGhlIHByZXZpb3VzIGNyaXRlcmlhIHdlcmUgbWV0LCB1c2UgdGhlIHBvc2l0aW9uIHRoYXQgZ29lcyBvZmYtc2NyZWVuIHRoZSBsZWFzdC5cbiAgICogQGRvY3MtcHJpdmF0ZVxuICAgKi9cbiAgYXBwbHkoKTogdm9pZCB7XG4gICAgLy8gV2Ugc2hvdWxkbid0IGRvIGFueXRoaW5nIGlmIHRoZSBzdHJhdGVneSB3YXMgZGlzcG9zZWQgb3Igd2UncmUgb24gdGhlIHNlcnZlci5cbiAgICBpZiAodGhpcy5faXNEaXNwb3NlZCB8fCAhdGhpcy5fcGxhdGZvcm0uaXNCcm93c2VyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSWYgdGhlIHBvc2l0aW9uIGhhcyBiZWVuIGFwcGxpZWQgYWxyZWFkeSAoZS5nLiB3aGVuIHRoZSBvdmVybGF5IHdhcyBvcGVuZWQpIGFuZCB0aGVcbiAgICAvLyBjb25zdW1lciBvcHRlZCBpbnRvIGxvY2tpbmcgaW4gdGhlIHBvc2l0aW9uLCByZS11c2UgdGhlIG9sZCBwb3NpdGlvbiwgaW4gb3JkZXIgdG9cbiAgICAvLyBwcmV2ZW50IHRoZSBvdmVybGF5IGZyb20ganVtcGluZyBhcm91bmQuXG4gICAgaWYgKCF0aGlzLl9pc0luaXRpYWxSZW5kZXIgJiYgdGhpcy5fcG9zaXRpb25Mb2NrZWQgJiYgdGhpcy5fbGFzdFBvc2l0aW9uKSB7XG4gICAgICB0aGlzLnJlYXBwbHlMYXN0UG9zaXRpb24oKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9jbGVhclBhbmVsQ2xhc3NlcygpO1xuICAgIHRoaXMuX3Jlc2V0T3ZlcmxheUVsZW1lbnRTdHlsZXMoKTtcbiAgICB0aGlzLl9yZXNldEJvdW5kaW5nQm94U3R5bGVzKCk7XG5cbiAgICAvLyBXZSBuZWVkIHRoZSBib3VuZGluZyByZWN0cyBmb3IgdGhlIG9yaWdpbiBhbmQgdGhlIG92ZXJsYXkgdG8gZGV0ZXJtaW5lIGhvdyB0byBwb3NpdGlvblxuICAgIC8vIHRoZSBvdmVybGF5IHJlbGF0aXZlIHRvIHRoZSBvcmlnaW4uXG4gICAgLy8gV2UgdXNlIHRoZSB2aWV3cG9ydCByZWN0IHRvIGRldGVybWluZSB3aGV0aGVyIGEgcG9zaXRpb24gd291bGQgZ28gb2ZmLXNjcmVlbi5cbiAgICB0aGlzLl92aWV3cG9ydFJlY3QgPSB0aGlzLl9nZXROYXJyb3dlZFZpZXdwb3J0UmVjdCgpO1xuICAgIHRoaXMuX29yaWdpblJlY3QgPSB0aGlzLl9nZXRPcmlnaW5SZWN0KCk7XG4gICAgdGhpcy5fb3ZlcmxheVJlY3QgPSB0aGlzLl9wYW5lLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgY29uc3Qgb3JpZ2luUmVjdCA9IHRoaXMuX29yaWdpblJlY3Q7XG4gICAgY29uc3Qgb3ZlcmxheVJlY3QgPSB0aGlzLl9vdmVybGF5UmVjdDtcbiAgICBjb25zdCB2aWV3cG9ydFJlY3QgPSB0aGlzLl92aWV3cG9ydFJlY3Q7XG5cbiAgICAvLyBQb3NpdGlvbnMgd2hlcmUgdGhlIG92ZXJsYXkgd2lsbCBmaXQgd2l0aCBmbGV4aWJsZSBkaW1lbnNpb25zLlxuICAgIGNvbnN0IGZsZXhpYmxlRml0czogRmxleGlibGVGaXRbXSA9IFtdO1xuXG4gICAgLy8gRmFsbGJhY2sgaWYgbm9uZSBvZiB0aGUgcHJlZmVycmVkIHBvc2l0aW9ucyBmaXQgd2l0aGluIHRoZSB2aWV3cG9ydC5cbiAgICBsZXQgZmFsbGJhY2s6IEZhbGxiYWNrUG9zaXRpb24gfCB1bmRlZmluZWQ7XG5cbiAgICAvLyBHbyB0aHJvdWdoIGVhY2ggb2YgdGhlIHByZWZlcnJlZCBwb3NpdGlvbnMgbG9va2luZyBmb3IgYSBnb29kIGZpdC5cbiAgICAvLyBJZiBhIGdvb2QgZml0IGlzIGZvdW5kLCBpdCB3aWxsIGJlIGFwcGxpZWQgaW1tZWRpYXRlbHkuXG4gICAgZm9yIChsZXQgcG9zIG9mIHRoaXMuX3ByZWZlcnJlZFBvc2l0aW9ucykge1xuICAgICAgLy8gR2V0IHRoZSBleGFjdCAoeCwgeSkgY29vcmRpbmF0ZSBmb3IgdGhlIHBvaW50LW9mLW9yaWdpbiBvbiB0aGUgb3JpZ2luIGVsZW1lbnQuXG4gICAgICBsZXQgb3JpZ2luUG9pbnQgPSB0aGlzLl9nZXRPcmlnaW5Qb2ludChvcmlnaW5SZWN0LCBwb3MpO1xuXG4gICAgICAvLyBGcm9tIHRoYXQgcG9pbnQtb2Ytb3JpZ2luLCBnZXQgdGhlIGV4YWN0ICh4LCB5KSBjb29yZGluYXRlIGZvciB0aGUgdG9wLWxlZnQgY29ybmVyIG9mIHRoZVxuICAgICAgLy8gb3ZlcmxheSBpbiB0aGlzIHBvc2l0aW9uLiBXZSB1c2UgdGhlIHRvcC1sZWZ0IGNvcm5lciBmb3IgY2FsY3VsYXRpb25zIGFuZCBsYXRlciB0cmFuc2xhdGVcbiAgICAgIC8vIHRoaXMgaW50byBhbiBhcHByb3ByaWF0ZSAodG9wLCBsZWZ0LCBib3R0b20sIHJpZ2h0KSBzdHlsZS5cbiAgICAgIGxldCBvdmVybGF5UG9pbnQgPSB0aGlzLl9nZXRPdmVybGF5UG9pbnQob3JpZ2luUG9pbnQsIG92ZXJsYXlSZWN0LCBwb3MpO1xuXG4gICAgICAvLyBDYWxjdWxhdGUgaG93IHdlbGwgdGhlIG92ZXJsYXkgd291bGQgZml0IGludG8gdGhlIHZpZXdwb3J0IHdpdGggdGhpcyBwb2ludC5cbiAgICAgIGxldCBvdmVybGF5Rml0ID0gdGhpcy5fZ2V0T3ZlcmxheUZpdChvdmVybGF5UG9pbnQsIG92ZXJsYXlSZWN0LCB2aWV3cG9ydFJlY3QsIHBvcyk7XG5cbiAgICAgIC8vIElmIHRoZSBvdmVybGF5LCB3aXRob3V0IGFueSBmdXJ0aGVyIHdvcmssIGZpdHMgaW50byB0aGUgdmlld3BvcnQsIHVzZSB0aGlzIHBvc2l0aW9uLlxuICAgICAgaWYgKG92ZXJsYXlGaXQuaXNDb21wbGV0ZWx5V2l0aGluVmlld3BvcnQpIHtcbiAgICAgICAgdGhpcy5faXNQdXNoZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5fYXBwbHlQb3NpdGlvbihwb3MsIG9yaWdpblBvaW50KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBJZiB0aGUgb3ZlcmxheSBoYXMgZmxleGlibGUgZGltZW5zaW9ucywgd2UgY2FuIHVzZSB0aGlzIHBvc2l0aW9uXG4gICAgICAvLyBzbyBsb25nIGFzIHRoZXJlJ3MgZW5vdWdoIHNwYWNlIGZvciB0aGUgbWluaW11bSBkaW1lbnNpb25zLlxuICAgICAgaWYgKHRoaXMuX2NhbkZpdFdpdGhGbGV4aWJsZURpbWVuc2lvbnMob3ZlcmxheUZpdCwgb3ZlcmxheVBvaW50LCB2aWV3cG9ydFJlY3QpKSB7XG4gICAgICAgIC8vIFNhdmUgcG9zaXRpb25zIHdoZXJlIHRoZSBvdmVybGF5IHdpbGwgZml0IHdpdGggZmxleGlibGUgZGltZW5zaW9ucy4gV2Ugd2lsbCB1c2UgdGhlc2VcbiAgICAgICAgLy8gaWYgbm9uZSBvZiB0aGUgcG9zaXRpb25zIGZpdCAqd2l0aG91dCogZmxleGlibGUgZGltZW5zaW9ucy5cbiAgICAgICAgZmxleGlibGVGaXRzLnB1c2goe1xuICAgICAgICAgIHBvc2l0aW9uOiBwb3MsXG4gICAgICAgICAgb3JpZ2luOiBvcmlnaW5Qb2ludCxcbiAgICAgICAgICBvdmVybGF5UmVjdCxcbiAgICAgICAgICBib3VuZGluZ0JveFJlY3Q6IHRoaXMuX2NhbGN1bGF0ZUJvdW5kaW5nQm94UmVjdChvcmlnaW5Qb2ludCwgcG9zKVxuICAgICAgICB9KTtcblxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgLy8gSWYgdGhlIGN1cnJlbnQgcHJlZmVycmVkIHBvc2l0aW9uIGRvZXMgbm90IGZpdCBvbiB0aGUgc2NyZWVuLCByZW1lbWJlciB0aGUgcG9zaXRpb25cbiAgICAgIC8vIGlmIGl0IGhhcyBtb3JlIHZpc2libGUgYXJlYSBvbi1zY3JlZW4gdGhhbiB3ZSd2ZSBzZWVuIGFuZCBtb3ZlIG9udG8gdGhlIG5leHQgcHJlZmVycmVkXG4gICAgICAvLyBwb3NpdGlvbi5cbiAgICAgIGlmICghZmFsbGJhY2sgfHwgZmFsbGJhY2sub3ZlcmxheUZpdC52aXNpYmxlQXJlYSA8IG92ZXJsYXlGaXQudmlzaWJsZUFyZWEpIHtcbiAgICAgICAgZmFsbGJhY2sgPSB7b3ZlcmxheUZpdCwgb3ZlcmxheVBvaW50LCBvcmlnaW5Qb2ludCwgcG9zaXRpb246IHBvcywgb3ZlcmxheVJlY3R9O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIElmIHRoZXJlIGFyZSBhbnkgcG9zaXRpb25zIHdoZXJlIHRoZSBvdmVybGF5IHdvdWxkIGZpdCB3aXRoIGZsZXhpYmxlIGRpbWVuc2lvbnMsIGNob29zZSB0aGVcbiAgICAvLyBvbmUgdGhhdCBoYXMgdGhlIGdyZWF0ZXN0IGFyZWEgYXZhaWxhYmxlIG1vZGlmaWVkIGJ5IHRoZSBwb3NpdGlvbidzIHdlaWdodFxuICAgIGlmIChmbGV4aWJsZUZpdHMubGVuZ3RoKSB7XG4gICAgICBsZXQgYmVzdEZpdDogRmxleGlibGVGaXQgfCBudWxsID0gbnVsbDtcbiAgICAgIGxldCBiZXN0U2NvcmUgPSAtMTtcbiAgICAgIGZvciAoY29uc3QgZml0IG9mIGZsZXhpYmxlRml0cykge1xuICAgICAgICBjb25zdCBzY29yZSA9XG4gICAgICAgICAgICBmaXQuYm91bmRpbmdCb3hSZWN0LndpZHRoICogZml0LmJvdW5kaW5nQm94UmVjdC5oZWlnaHQgKiAoZml0LnBvc2l0aW9uLndlaWdodCB8fCAxKTtcbiAgICAgICAgaWYgKHNjb3JlID4gYmVzdFNjb3JlKSB7XG4gICAgICAgICAgYmVzdFNjb3JlID0gc2NvcmU7XG4gICAgICAgICAgYmVzdEZpdCA9IGZpdDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aGlzLl9pc1B1c2hlZCA9IGZhbHNlO1xuICAgICAgdGhpcy5fYXBwbHlQb3NpdGlvbihiZXN0Rml0IS5wb3NpdGlvbiwgYmVzdEZpdCEub3JpZ2luKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBXaGVuIG5vbmUgb2YgdGhlIHByZWZlcnJlZCBwb3NpdGlvbnMgZml0IHdpdGhpbiB0aGUgdmlld3BvcnQsIHRha2UgdGhlIHBvc2l0aW9uXG4gICAgLy8gdGhhdCB3ZW50IG9mZi1zY3JlZW4gdGhlIGxlYXN0IGFuZCBhdHRlbXB0IHRvIHB1c2ggaXQgb24tc2NyZWVuLlxuICAgIGlmICh0aGlzLl9jYW5QdXNoKSB7XG4gICAgICAvLyBUT0RPKGplbGJvdXJuKTogYWZ0ZXIgcHVzaGluZywgdGhlIG9wZW5pbmcgXCJkaXJlY3Rpb25cIiBvZiB0aGUgb3ZlcmxheSBtaWdodCBub3QgbWFrZSBzZW5zZS5cbiAgICAgIHRoaXMuX2lzUHVzaGVkID0gdHJ1ZTtcbiAgICAgIHRoaXMuX2FwcGx5UG9zaXRpb24oZmFsbGJhY2shLnBvc2l0aW9uLCBmYWxsYmFjayEub3JpZ2luUG9pbnQpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEFsbCBvcHRpb25zIGZvciBnZXR0aW5nIHRoZSBvdmVybGF5IHdpdGhpbiB0aGUgdmlld3BvcnQgaGF2ZSBiZWVuIGV4aGF1c3RlZCwgc28gZ28gd2l0aCB0aGVcbiAgICAvLyBwb3NpdGlvbiB0aGF0IHdlbnQgb2ZmLXNjcmVlbiB0aGUgbGVhc3QuXG4gICAgdGhpcy5fYXBwbHlQb3NpdGlvbihmYWxsYmFjayEucG9zaXRpb24sIGZhbGxiYWNrIS5vcmlnaW5Qb2ludCk7XG4gIH1cblxuICBkZXRhY2goKTogdm9pZCB7XG4gICAgdGhpcy5fY2xlYXJQYW5lbENsYXNzZXMoKTtcbiAgICB0aGlzLl9sYXN0UG9zaXRpb24gPSBudWxsO1xuICAgIHRoaXMuX3ByZXZpb3VzUHVzaEFtb3VudCA9IG51bGw7XG4gICAgdGhpcy5fcmVzaXplU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICAvKiogQ2xlYW51cCBhZnRlciB0aGUgZWxlbWVudCBnZXRzIGRlc3Ryb3llZC4gKi9cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5faXNEaXNwb3NlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFdlIGNhbid0IHVzZSBgX3Jlc2V0Qm91bmRpbmdCb3hTdHlsZXNgIGhlcmUsIGJlY2F1c2UgaXQgcmVzZXRzXG4gICAgLy8gc29tZSBwcm9wZXJ0aWVzIHRvIHplcm8sIHJhdGhlciB0aGFuIHJlbW92aW5nIHRoZW0uXG4gICAgaWYgKHRoaXMuX2JvdW5kaW5nQm94KSB7XG4gICAgICBleHRlbmRTdHlsZXModGhpcy5fYm91bmRpbmdCb3guc3R5bGUsIHtcbiAgICAgICAgdG9wOiAnJyxcbiAgICAgICAgbGVmdDogJycsXG4gICAgICAgIHJpZ2h0OiAnJyxcbiAgICAgICAgYm90dG9tOiAnJyxcbiAgICAgICAgaGVpZ2h0OiAnJyxcbiAgICAgICAgd2lkdGg6ICcnLFxuICAgICAgICBhbGlnbkl0ZW1zOiAnJyxcbiAgICAgICAganVzdGlmeUNvbnRlbnQ6ICcnLFxuICAgICAgfSBhcyBDU1NTdHlsZURlY2xhcmF0aW9uKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fcGFuZSkge1xuICAgICAgdGhpcy5fcmVzZXRPdmVybGF5RWxlbWVudFN0eWxlcygpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9vdmVybGF5UmVmKSB7XG4gICAgICB0aGlzLl9vdmVybGF5UmVmLmhvc3RFbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoYm91bmRpbmdCb3hDbGFzcyk7XG4gICAgfVxuXG4gICAgdGhpcy5kZXRhY2goKTtcbiAgICB0aGlzLl9wb3NpdGlvbkNoYW5nZXMuY29tcGxldGUoKTtcbiAgICB0aGlzLl9vdmVybGF5UmVmID0gdGhpcy5fYm91bmRpbmdCb3ggPSBudWxsITtcbiAgICB0aGlzLl9pc0Rpc3Bvc2VkID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGlzIHJlLWFsaWducyB0aGUgb3ZlcmxheSBlbGVtZW50IHdpdGggdGhlIHRyaWdnZXIgaW4gaXRzIGxhc3QgY2FsY3VsYXRlZCBwb3NpdGlvbixcbiAgICogZXZlbiBpZiBhIHBvc2l0aW9uIGhpZ2hlciBpbiB0aGUgXCJwcmVmZXJyZWQgcG9zaXRpb25zXCIgbGlzdCB3b3VsZCBub3cgZml0LiBUaGlzXG4gICAqIGFsbG93cyBvbmUgdG8gcmUtYWxpZ24gdGhlIHBhbmVsIHdpdGhvdXQgY2hhbmdpbmcgdGhlIG9yaWVudGF0aW9uIG9mIHRoZSBwYW5lbC5cbiAgICovXG4gIHJlYXBwbHlMYXN0UG9zaXRpb24oKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9pc0Rpc3Bvc2VkICYmICghdGhpcy5fcGxhdGZvcm0gfHwgdGhpcy5fcGxhdGZvcm0uaXNCcm93c2VyKSkge1xuICAgICAgdGhpcy5fb3JpZ2luUmVjdCA9IHRoaXMuX2dldE9yaWdpblJlY3QoKTtcbiAgICAgIHRoaXMuX292ZXJsYXlSZWN0ID0gdGhpcy5fcGFuZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIHRoaXMuX3ZpZXdwb3J0UmVjdCA9IHRoaXMuX2dldE5hcnJvd2VkVmlld3BvcnRSZWN0KCk7XG5cbiAgICAgIGNvbnN0IGxhc3RQb3NpdGlvbiA9IHRoaXMuX2xhc3RQb3NpdGlvbiB8fCB0aGlzLl9wcmVmZXJyZWRQb3NpdGlvbnNbMF07XG4gICAgICBjb25zdCBvcmlnaW5Qb2ludCA9IHRoaXMuX2dldE9yaWdpblBvaW50KHRoaXMuX29yaWdpblJlY3QsIGxhc3RQb3NpdGlvbik7XG5cbiAgICAgIHRoaXMuX2FwcGx5UG9zaXRpb24obGFzdFBvc2l0aW9uLCBvcmlnaW5Qb2ludCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIGxpc3Qgb2YgU2Nyb2xsYWJsZSBjb250YWluZXJzIHRoYXQgaG9zdCB0aGUgb3JpZ2luIGVsZW1lbnQgc28gdGhhdFxuICAgKiBvbiByZXBvc2l0aW9uIHdlIGNhbiBldmFsdWF0ZSBpZiBpdCBvciB0aGUgb3ZlcmxheSBoYXMgYmVlbiBjbGlwcGVkIG9yIG91dHNpZGUgdmlldy4gRXZlcnlcbiAgICogU2Nyb2xsYWJsZSBtdXN0IGJlIGFuIGFuY2VzdG9yIGVsZW1lbnQgb2YgdGhlIHN0cmF0ZWd5J3Mgb3JpZ2luIGVsZW1lbnQuXG4gICAqL1xuICB3aXRoU2Nyb2xsYWJsZUNvbnRhaW5lcnMoc2Nyb2xsYWJsZXM6IENka1Njcm9sbGFibGVbXSk6IHRoaXMge1xuICAgIHRoaXMuX3Njcm9sbGFibGVzID0gc2Nyb2xsYWJsZXM7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBuZXcgcHJlZmVycmVkIHBvc2l0aW9ucy5cbiAgICogQHBhcmFtIHBvc2l0aW9ucyBMaXN0IG9mIHBvc2l0aW9ucyBvcHRpb25zIGZvciB0aGlzIG92ZXJsYXkuXG4gICAqL1xuICB3aXRoUG9zaXRpb25zKHBvc2l0aW9uczogQ29ubmVjdGVkUG9zaXRpb25bXSk6IHRoaXMge1xuICAgIHRoaXMuX3ByZWZlcnJlZFBvc2l0aW9ucyA9IHBvc2l0aW9ucztcblxuICAgIC8vIElmIHRoZSBsYXN0IGNhbGN1bGF0ZWQgcG9zaXRpb24gb2JqZWN0IGlzbid0IHBhcnQgb2YgdGhlIHBvc2l0aW9ucyBhbnltb3JlLCBjbGVhclxuICAgIC8vIGl0IGluIG9yZGVyIHRvIGF2b2lkIGl0IGJlaW5nIHBpY2tlZCB1cCBpZiB0aGUgY29uc3VtZXIgdHJpZXMgdG8gcmUtYXBwbHkuXG4gICAgaWYgKHBvc2l0aW9ucy5pbmRleE9mKHRoaXMuX2xhc3RQb3NpdGlvbiEpID09PSAtMSkge1xuICAgICAgdGhpcy5fbGFzdFBvc2l0aW9uID0gbnVsbDtcbiAgICB9XG5cbiAgICB0aGlzLl92YWxpZGF0ZVBvc2l0aW9ucygpO1xuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBhIG1pbmltdW0gZGlzdGFuY2UgdGhlIG92ZXJsYXkgbWF5IGJlIHBvc2l0aW9uZWQgdG8gdGhlIGVkZ2Ugb2YgdGhlIHZpZXdwb3J0LlxuICAgKiBAcGFyYW0gbWFyZ2luIFJlcXVpcmVkIG1hcmdpbiBiZXR3ZWVuIHRoZSBvdmVybGF5IGFuZCB0aGUgdmlld3BvcnQgZWRnZSBpbiBwaXhlbHMuXG4gICAqL1xuICB3aXRoVmlld3BvcnRNYXJnaW4obWFyZ2luOiBudW1iZXIpOiB0aGlzIHtcbiAgICB0aGlzLl92aWV3cG9ydE1hcmdpbiA9IG1hcmdpbjtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKiBTZXRzIHdoZXRoZXIgdGhlIG92ZXJsYXkncyB3aWR0aCBhbmQgaGVpZ2h0IGNhbiBiZSBjb25zdHJhaW5lZCB0byBmaXQgd2l0aGluIHRoZSB2aWV3cG9ydC4gKi9cbiAgd2l0aEZsZXhpYmxlRGltZW5zaW9ucyhmbGV4aWJsZURpbWVuc2lvbnMgPSB0cnVlKTogdGhpcyB7XG4gICAgdGhpcy5faGFzRmxleGlibGVEaW1lbnNpb25zID0gZmxleGlibGVEaW1lbnNpb25zO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqIFNldHMgd2hldGhlciB0aGUgb3ZlcmxheSBjYW4gZ3JvdyBhZnRlciB0aGUgaW5pdGlhbCBvcGVuIHZpYSBmbGV4aWJsZSB3aWR0aC9oZWlnaHQuICovXG4gIHdpdGhHcm93QWZ0ZXJPcGVuKGdyb3dBZnRlck9wZW4gPSB0cnVlKTogdGhpcyB7XG4gICAgdGhpcy5fZ3Jvd0FmdGVyT3BlbiA9IGdyb3dBZnRlck9wZW47XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKiogU2V0cyB3aGV0aGVyIHRoZSBvdmVybGF5IGNhbiBiZSBwdXNoZWQgb24tc2NyZWVuIGlmIG5vbmUgb2YgdGhlIHByb3ZpZGVkIHBvc2l0aW9ucyBmaXQuICovXG4gIHdpdGhQdXNoKGNhblB1c2ggPSB0cnVlKTogdGhpcyB7XG4gICAgdGhpcy5fY2FuUHVzaCA9IGNhblB1c2g7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB3aGV0aGVyIHRoZSBvdmVybGF5J3MgcG9zaXRpb24gc2hvdWxkIGJlIGxvY2tlZCBpbiBhZnRlciBpdCBpcyBwb3NpdGlvbmVkXG4gICAqIGluaXRpYWxseS4gV2hlbiBhbiBvdmVybGF5IGlzIGxvY2tlZCBpbiwgaXQgd29uJ3QgYXR0ZW1wdCB0byByZXBvc2l0aW9uIGl0c2VsZlxuICAgKiB3aGVuIHRoZSBwb3NpdGlvbiBpcyByZS1hcHBsaWVkIChlLmcuIHdoZW4gdGhlIHVzZXIgc2Nyb2xscyBhd2F5KS5cbiAgICogQHBhcmFtIGlzTG9ja2VkIFdoZXRoZXIgdGhlIG92ZXJsYXkgc2hvdWxkIGxvY2tlZCBpbi5cbiAgICovXG4gIHdpdGhMb2NrZWRQb3NpdGlvbihpc0xvY2tlZCA9IHRydWUpOiB0aGlzIHtcbiAgICB0aGlzLl9wb3NpdGlvbkxvY2tlZCA9IGlzTG9ja2VkO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIG9yaWdpbiwgcmVsYXRpdmUgdG8gd2hpY2ggdG8gcG9zaXRpb24gdGhlIG92ZXJsYXkuXG4gICAqIFVzaW5nIGFuIGVsZW1lbnQgb3JpZ2luIGlzIHVzZWZ1bCBmb3IgYnVpbGRpbmcgY29tcG9uZW50cyB0aGF0IG5lZWQgdG8gYmUgcG9zaXRpb25lZFxuICAgKiByZWxhdGl2ZWx5IHRvIGEgdHJpZ2dlciAoZS5nLiBkcm9wZG93biBtZW51cyBvciB0b29sdGlwcyksIHdoZXJlYXMgdXNpbmcgYSBwb2ludCBjYW4gYmVcbiAgICogdXNlZCBmb3IgY2FzZXMgbGlrZSBjb250ZXh0dWFsIG1lbnVzIHdoaWNoIG9wZW4gcmVsYXRpdmUgdG8gdGhlIHVzZXIncyBwb2ludGVyLlxuICAgKiBAcGFyYW0gb3JpZ2luIFJlZmVyZW5jZSB0byB0aGUgbmV3IG9yaWdpbi5cbiAgICovXG4gIHNldE9yaWdpbihvcmlnaW46IEZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneU9yaWdpbik6IHRoaXMge1xuICAgIHRoaXMuX29yaWdpbiA9IG9yaWdpbjtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBkZWZhdWx0IG9mZnNldCBmb3IgdGhlIG92ZXJsYXkncyBjb25uZWN0aW9uIHBvaW50IG9uIHRoZSB4LWF4aXMuXG4gICAqIEBwYXJhbSBvZmZzZXQgTmV3IG9mZnNldCBpbiB0aGUgWCBheGlzLlxuICAgKi9cbiAgd2l0aERlZmF1bHRPZmZzZXRYKG9mZnNldDogbnVtYmVyKTogdGhpcyB7XG4gICAgdGhpcy5fb2Zmc2V0WCA9IG9mZnNldDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBkZWZhdWx0IG9mZnNldCBmb3IgdGhlIG92ZXJsYXkncyBjb25uZWN0aW9uIHBvaW50IG9uIHRoZSB5LWF4aXMuXG4gICAqIEBwYXJhbSBvZmZzZXQgTmV3IG9mZnNldCBpbiB0aGUgWSBheGlzLlxuICAgKi9cbiAgd2l0aERlZmF1bHRPZmZzZXRZKG9mZnNldDogbnVtYmVyKTogdGhpcyB7XG4gICAgdGhpcy5fb2Zmc2V0WSA9IG9mZnNldDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25maWd1cmVzIHRoYXQgdGhlIHBvc2l0aW9uIHN0cmF0ZWd5IHNob3VsZCBzZXQgYSBgdHJhbnNmb3JtLW9yaWdpbmAgb24gc29tZSBlbGVtZW50c1xuICAgKiBpbnNpZGUgdGhlIG92ZXJsYXksIGRlcGVuZGluZyBvbiB0aGUgY3VycmVudCBwb3NpdGlvbiB0aGF0IGlzIGJlaW5nIGFwcGxpZWQuIFRoaXMgaXNcbiAgICogdXNlZnVsIGZvciB0aGUgY2FzZXMgd2hlcmUgdGhlIG9yaWdpbiBvZiBhbiBhbmltYXRpb24gY2FuIGNoYW5nZSBkZXBlbmRpbmcgb24gdGhlXG4gICAqIGFsaWdubWVudCBvZiB0aGUgb3ZlcmxheS5cbiAgICogQHBhcmFtIHNlbGVjdG9yIENTUyBzZWxlY3RvciB0aGF0IHdpbGwgYmUgdXNlZCB0byBmaW5kIHRoZSB0YXJnZXRcbiAgICogICAgZWxlbWVudHMgb250byB3aGljaCB0byBzZXQgdGhlIHRyYW5zZm9ybSBvcmlnaW4uXG4gICAqL1xuICB3aXRoVHJhbnNmb3JtT3JpZ2luT24oc2VsZWN0b3I6IHN0cmluZyk6IHRoaXMge1xuICAgIHRoaXMuX3RyYW5zZm9ybU9yaWdpblNlbGVjdG9yID0gc2VsZWN0b3I7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgKHgsIHkpIGNvb3JkaW5hdGUgb2YgYSBjb25uZWN0aW9uIHBvaW50IG9uIHRoZSBvcmlnaW4gYmFzZWQgb24gYSByZWxhdGl2ZSBwb3NpdGlvbi5cbiAgICovXG4gIHByaXZhdGUgX2dldE9yaWdpblBvaW50KG9yaWdpblJlY3Q6IENsaWVudFJlY3QsIHBvczogQ29ubmVjdGVkUG9zaXRpb24pOiBQb2ludCB7XG4gICAgbGV0IHg6IG51bWJlcjtcbiAgICBpZiAocG9zLm9yaWdpblggPT0gJ2NlbnRlcicpIHtcbiAgICAgIC8vIE5vdGU6IHdoZW4gY2VudGVyaW5nIHdlIHNob3VsZCBhbHdheXMgdXNlIHRoZSBgbGVmdGBcbiAgICAgIC8vIG9mZnNldCwgb3RoZXJ3aXNlIHRoZSBwb3NpdGlvbiB3aWxsIGJlIHdyb25nIGluIFJUTC5cbiAgICAgIHggPSBvcmlnaW5SZWN0LmxlZnQgKyAob3JpZ2luUmVjdC53aWR0aCAvIDIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBzdGFydFggPSB0aGlzLl9pc1J0bCgpID8gb3JpZ2luUmVjdC5yaWdodCA6IG9yaWdpblJlY3QubGVmdDtcbiAgICAgIGNvbnN0IGVuZFggPSB0aGlzLl9pc1J0bCgpID8gb3JpZ2luUmVjdC5sZWZ0IDogb3JpZ2luUmVjdC5yaWdodDtcbiAgICAgIHggPSBwb3Mub3JpZ2luWCA9PSAnc3RhcnQnID8gc3RhcnRYIDogZW5kWDtcbiAgICB9XG5cbiAgICBsZXQgeTogbnVtYmVyO1xuICAgIGlmIChwb3Mub3JpZ2luWSA9PSAnY2VudGVyJykge1xuICAgICAgeSA9IG9yaWdpblJlY3QudG9wICsgKG9yaWdpblJlY3QuaGVpZ2h0IC8gMik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHkgPSBwb3Mub3JpZ2luWSA9PSAndG9wJyA/IG9yaWdpblJlY3QudG9wIDogb3JpZ2luUmVjdC5ib3R0b207XG4gICAgfVxuXG4gICAgcmV0dXJuIHt4LCB5fTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIEdldHMgdGhlICh4LCB5KSBjb29yZGluYXRlIG9mIHRoZSB0b3AtbGVmdCBjb3JuZXIgb2YgdGhlIG92ZXJsYXkgZ2l2ZW4gYSBnaXZlbiBwb3NpdGlvbiBhbmRcbiAgICogb3JpZ2luIHBvaW50IHRvIHdoaWNoIHRoZSBvdmVybGF5IHNob3VsZCBiZSBjb25uZWN0ZWQuXG4gICAqL1xuICBwcml2YXRlIF9nZXRPdmVybGF5UG9pbnQoXG4gICAgICBvcmlnaW5Qb2ludDogUG9pbnQsXG4gICAgICBvdmVybGF5UmVjdDogQ2xpZW50UmVjdCxcbiAgICAgIHBvczogQ29ubmVjdGVkUG9zaXRpb24pOiBQb2ludCB7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIChvdmVybGF5U3RhcnRYLCBvdmVybGF5U3RhcnRZKSwgdGhlIHN0YXJ0IG9mIHRoZVxuICAgIC8vIHBvdGVudGlhbCBvdmVybGF5IHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSBvcmlnaW4gcG9pbnQuXG4gICAgbGV0IG92ZXJsYXlTdGFydFg6IG51bWJlcjtcbiAgICBpZiAocG9zLm92ZXJsYXlYID09ICdjZW50ZXInKSB7XG4gICAgICBvdmVybGF5U3RhcnRYID0gLW92ZXJsYXlSZWN0LndpZHRoIC8gMjtcbiAgICB9IGVsc2UgaWYgKHBvcy5vdmVybGF5WCA9PT0gJ3N0YXJ0Jykge1xuICAgICAgb3ZlcmxheVN0YXJ0WCA9IHRoaXMuX2lzUnRsKCkgPyAtb3ZlcmxheVJlY3Qud2lkdGggOiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBvdmVybGF5U3RhcnRYID0gdGhpcy5faXNSdGwoKSA/IDAgOiAtb3ZlcmxheVJlY3Qud2lkdGg7XG4gICAgfVxuXG4gICAgbGV0IG92ZXJsYXlTdGFydFk6IG51bWJlcjtcbiAgICBpZiAocG9zLm92ZXJsYXlZID09ICdjZW50ZXInKSB7XG4gICAgICBvdmVybGF5U3RhcnRZID0gLW92ZXJsYXlSZWN0LmhlaWdodCAvIDI7XG4gICAgfSBlbHNlIHtcbiAgICAgIG92ZXJsYXlTdGFydFkgPSBwb3Mub3ZlcmxheVkgPT0gJ3RvcCcgPyAwIDogLW92ZXJsYXlSZWN0LmhlaWdodDtcbiAgICB9XG5cbiAgICAvLyBUaGUgKHgsIHkpIGNvb3JkaW5hdGVzIG9mIHRoZSBvdmVybGF5LlxuICAgIHJldHVybiB7XG4gICAgICB4OiBvcmlnaW5Qb2ludC54ICsgb3ZlcmxheVN0YXJ0WCxcbiAgICAgIHk6IG9yaWdpblBvaW50LnkgKyBvdmVybGF5U3RhcnRZLFxuICAgIH07XG4gIH1cblxuICAvKiogR2V0cyBob3cgd2VsbCBhbiBvdmVybGF5IGF0IHRoZSBnaXZlbiBwb2ludCB3aWxsIGZpdCB3aXRoaW4gdGhlIHZpZXdwb3J0LiAqL1xuICBwcml2YXRlIF9nZXRPdmVybGF5Rml0KHBvaW50OiBQb2ludCwgcmF3T3ZlcmxheVJlY3Q6IENsaWVudFJlY3QsIHZpZXdwb3J0OiBDbGllbnRSZWN0LFxuICAgIHBvc2l0aW9uOiBDb25uZWN0ZWRQb3NpdGlvbik6IE92ZXJsYXlGaXQge1xuXG4gICAgLy8gUm91bmQgdGhlIG92ZXJsYXkgcmVjdCB3aGVuIGNvbXBhcmluZyBhZ2FpbnN0IHRoZVxuICAgIC8vIHZpZXdwb3J0LCBiZWNhdXNlIHRoZSB2aWV3cG9ydCBpcyBhbHdheXMgcm91bmRlZC5cbiAgICBjb25zdCBvdmVybGF5ID0gZ2V0Um91bmRlZEJvdW5kaW5nQ2xpZW50UmVjdChyYXdPdmVybGF5UmVjdCk7XG4gICAgbGV0IHt4LCB5fSA9IHBvaW50O1xuICAgIGxldCBvZmZzZXRYID0gdGhpcy5fZ2V0T2Zmc2V0KHBvc2l0aW9uLCAneCcpO1xuICAgIGxldCBvZmZzZXRZID0gdGhpcy5fZ2V0T2Zmc2V0KHBvc2l0aW9uLCAneScpO1xuXG4gICAgLy8gQWNjb3VudCBmb3IgdGhlIG9mZnNldHMgc2luY2UgdGhleSBjb3VsZCBwdXNoIHRoZSBvdmVybGF5IG91dCBvZiB0aGUgdmlld3BvcnQuXG4gICAgaWYgKG9mZnNldFgpIHtcbiAgICAgIHggKz0gb2Zmc2V0WDtcbiAgICB9XG5cbiAgICBpZiAob2Zmc2V0WSkge1xuICAgICAgeSArPSBvZmZzZXRZO1xuICAgIH1cblxuICAgIC8vIEhvdyBtdWNoIHRoZSBvdmVybGF5IHdvdWxkIG92ZXJmbG93IGF0IHRoaXMgcG9zaXRpb24sIG9uIGVhY2ggc2lkZS5cbiAgICBsZXQgbGVmdE92ZXJmbG93ID0gMCAtIHg7XG4gICAgbGV0IHJpZ2h0T3ZlcmZsb3cgPSAoeCArIG92ZXJsYXkud2lkdGgpIC0gdmlld3BvcnQud2lkdGg7XG4gICAgbGV0IHRvcE92ZXJmbG93ID0gMCAtIHk7XG4gICAgbGV0IGJvdHRvbU92ZXJmbG93ID0gKHkgKyBvdmVybGF5LmhlaWdodCkgLSB2aWV3cG9ydC5oZWlnaHQ7XG5cbiAgICAvLyBWaXNpYmxlIHBhcnRzIG9mIHRoZSBlbGVtZW50IG9uIGVhY2ggYXhpcy5cbiAgICBsZXQgdmlzaWJsZVdpZHRoID0gdGhpcy5fc3VidHJhY3RPdmVyZmxvd3Mob3ZlcmxheS53aWR0aCwgbGVmdE92ZXJmbG93LCByaWdodE92ZXJmbG93KTtcbiAgICBsZXQgdmlzaWJsZUhlaWdodCA9IHRoaXMuX3N1YnRyYWN0T3ZlcmZsb3dzKG92ZXJsYXkuaGVpZ2h0LCB0b3BPdmVyZmxvdywgYm90dG9tT3ZlcmZsb3cpO1xuICAgIGxldCB2aXNpYmxlQXJlYSA9IHZpc2libGVXaWR0aCAqIHZpc2libGVIZWlnaHQ7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdmlzaWJsZUFyZWEsXG4gICAgICBpc0NvbXBsZXRlbHlXaXRoaW5WaWV3cG9ydDogKG92ZXJsYXkud2lkdGggKiBvdmVybGF5LmhlaWdodCkgPT09IHZpc2libGVBcmVhLFxuICAgICAgZml0c0luVmlld3BvcnRWZXJ0aWNhbGx5OiB2aXNpYmxlSGVpZ2h0ID09PSBvdmVybGF5LmhlaWdodCxcbiAgICAgIGZpdHNJblZpZXdwb3J0SG9yaXpvbnRhbGx5OiB2aXNpYmxlV2lkdGggPT0gb3ZlcmxheS53aWR0aCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIG92ZXJsYXkgY2FuIGZpdCB3aXRoaW4gdGhlIHZpZXdwb3J0IHdoZW4gaXQgbWF5IHJlc2l6ZSBlaXRoZXIgaXRzIHdpZHRoIG9yIGhlaWdodC5cbiAgICogQHBhcmFtIGZpdCBIb3cgd2VsbCB0aGUgb3ZlcmxheSBmaXRzIGluIHRoZSB2aWV3cG9ydCBhdCBzb21lIHBvc2l0aW9uLlxuICAgKiBAcGFyYW0gcG9pbnQgVGhlICh4LCB5KSBjb29yZGluYXRlcyBvZiB0aGUgb3ZlcmxhdCBhdCBzb21lIHBvc2l0aW9uLlxuICAgKiBAcGFyYW0gdmlld3BvcnQgVGhlIGdlb21ldHJ5IG9mIHRoZSB2aWV3cG9ydC5cbiAgICovXG4gIHByaXZhdGUgX2NhbkZpdFdpdGhGbGV4aWJsZURpbWVuc2lvbnMoZml0OiBPdmVybGF5Rml0LCBwb2ludDogUG9pbnQsIHZpZXdwb3J0OiBDbGllbnRSZWN0KSB7XG4gICAgaWYgKHRoaXMuX2hhc0ZsZXhpYmxlRGltZW5zaW9ucykge1xuICAgICAgY29uc3QgYXZhaWxhYmxlSGVpZ2h0ID0gdmlld3BvcnQuYm90dG9tIC0gcG9pbnQueTtcbiAgICAgIGNvbnN0IGF2YWlsYWJsZVdpZHRoID0gdmlld3BvcnQucmlnaHQgLSBwb2ludC54O1xuICAgICAgY29uc3QgbWluSGVpZ2h0ID0gZ2V0UGl4ZWxWYWx1ZSh0aGlzLl9vdmVybGF5UmVmLmdldENvbmZpZygpLm1pbkhlaWdodCk7XG4gICAgICBjb25zdCBtaW5XaWR0aCA9IGdldFBpeGVsVmFsdWUodGhpcy5fb3ZlcmxheVJlZi5nZXRDb25maWcoKS5taW5XaWR0aCk7XG5cbiAgICAgIGNvbnN0IHZlcnRpY2FsRml0ID0gZml0LmZpdHNJblZpZXdwb3J0VmVydGljYWxseSB8fFxuICAgICAgICAgIChtaW5IZWlnaHQgIT0gbnVsbCAmJiBtaW5IZWlnaHQgPD0gYXZhaWxhYmxlSGVpZ2h0KTtcbiAgICAgIGNvbnN0IGhvcml6b250YWxGaXQgPSBmaXQuZml0c0luVmlld3BvcnRIb3Jpem9udGFsbHkgfHxcbiAgICAgICAgICAobWluV2lkdGggIT0gbnVsbCAmJiBtaW5XaWR0aCA8PSBhdmFpbGFibGVXaWR0aCk7XG5cbiAgICAgIHJldHVybiB2ZXJ0aWNhbEZpdCAmJiBob3Jpem9udGFsRml0O1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgcG9pbnQgYXQgd2hpY2ggdGhlIG92ZXJsYXkgY2FuIGJlIFwicHVzaGVkXCIgb24tc2NyZWVuLiBJZiB0aGUgb3ZlcmxheSBpcyBsYXJnZXIgdGhhblxuICAgKiB0aGUgdmlld3BvcnQsIHRoZSB0b3AtbGVmdCBjb3JuZXIgd2lsbCBiZSBwdXNoZWQgb24tc2NyZWVuICh3aXRoIG92ZXJmbG93IG9jY3VyaW5nIG9uIHRoZVxuICAgKiByaWdodCBhbmQgYm90dG9tKS5cbiAgICpcbiAgICogQHBhcmFtIHN0YXJ0IFN0YXJ0aW5nIHBvaW50IGZyb20gd2hpY2ggdGhlIG92ZXJsYXkgaXMgcHVzaGVkLlxuICAgKiBAcGFyYW0gb3ZlcmxheSBEaW1lbnNpb25zIG9mIHRoZSBvdmVybGF5LlxuICAgKiBAcGFyYW0gc2Nyb2xsUG9zaXRpb24gQ3VycmVudCB2aWV3cG9ydCBzY3JvbGwgcG9zaXRpb24uXG4gICAqIEByZXR1cm5zIFRoZSBwb2ludCBhdCB3aGljaCB0byBwb3NpdGlvbiB0aGUgb3ZlcmxheSBhZnRlciBwdXNoaW5nLiBUaGlzIGlzIGVmZmVjdGl2ZWx5IGEgbmV3XG4gICAqICAgICBvcmlnaW5Qb2ludC5cbiAgICovXG4gIHByaXZhdGUgX3B1c2hPdmVybGF5T25TY3JlZW4oc3RhcnQ6IFBvaW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd092ZXJsYXlSZWN0OiBDbGllbnRSZWN0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFBvc2l0aW9uOiBWaWV3cG9ydFNjcm9sbFBvc2l0aW9uKTogUG9pbnQge1xuICAgIC8vIElmIHRoZSBwb3NpdGlvbiBpcyBsb2NrZWQgYW5kIHdlJ3ZlIHB1c2hlZCB0aGUgb3ZlcmxheSBhbHJlYWR5LCByZXVzZSB0aGUgcHJldmlvdXMgcHVzaFxuICAgIC8vIGFtb3VudCwgcmF0aGVyIHRoYW4gcHVzaGluZyBpdCBhZ2Fpbi4gSWYgd2Ugd2VyZSB0byBjb250aW51ZSBwdXNoaW5nLCB0aGUgZWxlbWVudCB3b3VsZFxuICAgIC8vIHJlbWFpbiBpbiB0aGUgdmlld3BvcnQsIHdoaWNoIGdvZXMgYWdhaW5zdCB0aGUgZXhwZWN0YXRpb25zIHdoZW4gcG9zaXRpb24gbG9ja2luZyBpcyBlbmFibGVkLlxuICAgIGlmICh0aGlzLl9wcmV2aW91c1B1c2hBbW91bnQgJiYgdGhpcy5fcG9zaXRpb25Mb2NrZWQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHg6IHN0YXJ0LnggKyB0aGlzLl9wcmV2aW91c1B1c2hBbW91bnQueCxcbiAgICAgICAgeTogc3RhcnQueSArIHRoaXMuX3ByZXZpb3VzUHVzaEFtb3VudC55XG4gICAgICB9O1xuICAgIH1cblxuICAgIC8vIFJvdW5kIHRoZSBvdmVybGF5IHJlY3Qgd2hlbiBjb21wYXJpbmcgYWdhaW5zdCB0aGVcbiAgICAvLyB2aWV3cG9ydCwgYmVjYXVzZSB0aGUgdmlld3BvcnQgaXMgYWx3YXlzIHJvdW5kZWQuXG4gICAgY29uc3Qgb3ZlcmxheSA9IGdldFJvdW5kZWRCb3VuZGluZ0NsaWVudFJlY3QocmF3T3ZlcmxheVJlY3QpO1xuICAgIGNvbnN0IHZpZXdwb3J0ID0gdGhpcy5fdmlld3BvcnRSZWN0O1xuXG4gICAgLy8gRGV0ZXJtaW5lIGhvdyBtdWNoIHRoZSBvdmVybGF5IGdvZXMgb3V0c2lkZSB0aGUgdmlld3BvcnQgb24gZWFjaFxuICAgIC8vIHNpZGUsIHdoaWNoIHdlJ2xsIHVzZSB0byBkZWNpZGUgd2hpY2ggZGlyZWN0aW9uIHRvIHB1c2ggaXQuXG4gICAgY29uc3Qgb3ZlcmZsb3dSaWdodCA9IE1hdGgubWF4KHN0YXJ0LnggKyBvdmVybGF5LndpZHRoIC0gdmlld3BvcnQud2lkdGgsIDApO1xuICAgIGNvbnN0IG92ZXJmbG93Qm90dG9tID0gTWF0aC5tYXgoc3RhcnQueSArIG92ZXJsYXkuaGVpZ2h0IC0gdmlld3BvcnQuaGVpZ2h0LCAwKTtcbiAgICBjb25zdCBvdmVyZmxvd1RvcCA9IE1hdGgubWF4KHZpZXdwb3J0LnRvcCAtIHNjcm9sbFBvc2l0aW9uLnRvcCAtIHN0YXJ0LnksIDApO1xuICAgIGNvbnN0IG92ZXJmbG93TGVmdCA9IE1hdGgubWF4KHZpZXdwb3J0LmxlZnQgLSBzY3JvbGxQb3NpdGlvbi5sZWZ0IC0gc3RhcnQueCwgMCk7XG5cbiAgICAvLyBBbW91bnQgYnkgd2hpY2ggdG8gcHVzaCB0aGUgb3ZlcmxheSBpbiBlYWNoIGF4aXMgc3VjaCB0aGF0IGl0IHJlbWFpbnMgb24tc2NyZWVuLlxuICAgIGxldCBwdXNoWCA9IDA7XG4gICAgbGV0IHB1c2hZID0gMDtcblxuICAgIC8vIElmIHRoZSBvdmVybGF5IGZpdHMgY29tcGxldGVseSB3aXRoaW4gdGhlIGJvdW5kcyBvZiB0aGUgdmlld3BvcnQsIHB1c2ggaXQgZnJvbSB3aGljaGV2ZXJcbiAgICAvLyBkaXJlY3Rpb24gaXMgZ29lcyBvZmYtc2NyZWVuLiBPdGhlcndpc2UsIHB1c2ggdGhlIHRvcC1sZWZ0IGNvcm5lciBzdWNoIHRoYXQgaXRzIGluIHRoZVxuICAgIC8vIHZpZXdwb3J0IGFuZCBhbGxvdyBmb3IgdGhlIHRyYWlsaW5nIGVuZCBvZiB0aGUgb3ZlcmxheSB0byBnbyBvdXQgb2YgYm91bmRzLlxuICAgIGlmIChvdmVybGF5LndpZHRoIDw9IHZpZXdwb3J0LndpZHRoKSB7XG4gICAgICBwdXNoWCA9IG92ZXJmbG93TGVmdCB8fCAtb3ZlcmZsb3dSaWdodDtcbiAgICB9IGVsc2Uge1xuICAgICAgcHVzaFggPSBzdGFydC54IDwgdGhpcy5fdmlld3BvcnRNYXJnaW4gPyAodmlld3BvcnQubGVmdCAtIHNjcm9sbFBvc2l0aW9uLmxlZnQpIC0gc3RhcnQueCA6IDA7XG4gICAgfVxuXG4gICAgaWYgKG92ZXJsYXkuaGVpZ2h0IDw9IHZpZXdwb3J0LmhlaWdodCkge1xuICAgICAgcHVzaFkgPSBvdmVyZmxvd1RvcCB8fCAtb3ZlcmZsb3dCb3R0b207XG4gICAgfSBlbHNlIHtcbiAgICAgIHB1c2hZID0gc3RhcnQueSA8IHRoaXMuX3ZpZXdwb3J0TWFyZ2luID8gKHZpZXdwb3J0LnRvcCAtIHNjcm9sbFBvc2l0aW9uLnRvcCkgLSBzdGFydC55IDogMDtcbiAgICB9XG5cbiAgICB0aGlzLl9wcmV2aW91c1B1c2hBbW91bnQgPSB7eDogcHVzaFgsIHk6IHB1c2hZfTtcblxuICAgIHJldHVybiB7XG4gICAgICB4OiBzdGFydC54ICsgcHVzaFgsXG4gICAgICB5OiBzdGFydC55ICsgcHVzaFksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBsaWVzIGEgY29tcHV0ZWQgcG9zaXRpb24gdG8gdGhlIG92ZXJsYXkgYW5kIGVtaXRzIGEgcG9zaXRpb24gY2hhbmdlLlxuICAgKiBAcGFyYW0gcG9zaXRpb24gVGhlIHBvc2l0aW9uIHByZWZlcmVuY2VcbiAgICogQHBhcmFtIG9yaWdpblBvaW50IFRoZSBwb2ludCBvbiB0aGUgb3JpZ2luIGVsZW1lbnQgd2hlcmUgdGhlIG92ZXJsYXkgaXMgY29ubmVjdGVkLlxuICAgKi9cbiAgcHJpdmF0ZSBfYXBwbHlQb3NpdGlvbihwb3NpdGlvbjogQ29ubmVjdGVkUG9zaXRpb24sIG9yaWdpblBvaW50OiBQb2ludCkge1xuICAgIHRoaXMuX3NldFRyYW5zZm9ybU9yaWdpbihwb3NpdGlvbik7XG4gICAgdGhpcy5fc2V0T3ZlcmxheUVsZW1lbnRTdHlsZXMob3JpZ2luUG9pbnQsIHBvc2l0aW9uKTtcbiAgICB0aGlzLl9zZXRCb3VuZGluZ0JveFN0eWxlcyhvcmlnaW5Qb2ludCwgcG9zaXRpb24pO1xuXG4gICAgaWYgKHBvc2l0aW9uLnBhbmVsQ2xhc3MpIHtcbiAgICAgIHRoaXMuX2FkZFBhbmVsQ2xhc3Nlcyhwb3NpdGlvbi5wYW5lbENsYXNzKTtcbiAgICB9XG5cbiAgICAvLyBTYXZlIHRoZSBsYXN0IGNvbm5lY3RlZCBwb3NpdGlvbiBpbiBjYXNlIHRoZSBwb3NpdGlvbiBuZWVkcyB0byBiZSByZS1jYWxjdWxhdGVkLlxuICAgIHRoaXMuX2xhc3RQb3NpdGlvbiA9IHBvc2l0aW9uO1xuXG4gICAgLy8gTm90aWZ5IHRoYXQgdGhlIHBvc2l0aW9uIGhhcyBiZWVuIGNoYW5nZWQgYWxvbmcgd2l0aCBpdHMgY2hhbmdlIHByb3BlcnRpZXMuXG4gICAgLy8gV2Ugb25seSBlbWl0IGlmIHdlJ3ZlIGdvdCBhbnkgc3Vic2NyaXB0aW9ucywgYmVjYXVzZSB0aGUgc2Nyb2xsIHZpc2liaWxpdHlcbiAgICAvLyBjYWxjdWxjYXRpb25zIGNhbiBiZSBzb21ld2hhdCBleHBlbnNpdmUuXG4gICAgaWYgKHRoaXMuX3Bvc2l0aW9uQ2hhbmdlcy5vYnNlcnZlcnMubGVuZ3RoKSB7XG4gICAgICBjb25zdCBzY3JvbGxhYmxlVmlld1Byb3BlcnRpZXMgPSB0aGlzLl9nZXRTY3JvbGxWaXNpYmlsaXR5KCk7XG4gICAgICBjb25zdCBjaGFuZ2VFdmVudCA9IG5ldyBDb25uZWN0ZWRPdmVybGF5UG9zaXRpb25DaGFuZ2UocG9zaXRpb24sIHNjcm9sbGFibGVWaWV3UHJvcGVydGllcyk7XG4gICAgICB0aGlzLl9wb3NpdGlvbkNoYW5nZXMubmV4dChjaGFuZ2VFdmVudCk7XG4gICAgfVxuXG4gICAgdGhpcy5faXNJbml0aWFsUmVuZGVyID0gZmFsc2U7XG4gIH1cblxuICAvKiogU2V0cyB0aGUgdHJhbnNmb3JtIG9yaWdpbiBiYXNlZCBvbiB0aGUgY29uZmlndXJlZCBzZWxlY3RvciBhbmQgdGhlIHBhc3NlZC1pbiBwb3NpdGlvbi4gICovXG4gIHByaXZhdGUgX3NldFRyYW5zZm9ybU9yaWdpbihwb3NpdGlvbjogQ29ubmVjdGVkUG9zaXRpb24pIHtcbiAgICBpZiAoIXRoaXMuX3RyYW5zZm9ybU9yaWdpblNlbGVjdG9yKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZWxlbWVudHM6IE5vZGVMaXN0T2Y8SFRNTEVsZW1lbnQ+ID1cbiAgICAgICAgdGhpcy5fYm91bmRpbmdCb3ghLnF1ZXJ5U2VsZWN0b3JBbGwodGhpcy5fdHJhbnNmb3JtT3JpZ2luU2VsZWN0b3IpO1xuICAgIGxldCB4T3JpZ2luOiAnbGVmdCcgfCAncmlnaHQnIHwgJ2NlbnRlcic7XG4gICAgbGV0IHlPcmlnaW46ICd0b3AnIHwgJ2JvdHRvbScgfCAnY2VudGVyJyA9IHBvc2l0aW9uLm92ZXJsYXlZO1xuXG4gICAgaWYgKHBvc2l0aW9uLm92ZXJsYXlYID09PSAnY2VudGVyJykge1xuICAgICAgeE9yaWdpbiA9ICdjZW50ZXInO1xuICAgIH0gZWxzZSBpZiAodGhpcy5faXNSdGwoKSkge1xuICAgICAgeE9yaWdpbiA9IHBvc2l0aW9uLm92ZXJsYXlYID09PSAnc3RhcnQnID8gJ3JpZ2h0JyA6ICdsZWZ0JztcbiAgICB9IGVsc2Uge1xuICAgICAgeE9yaWdpbiA9IHBvc2l0aW9uLm92ZXJsYXlYID09PSAnc3RhcnQnID8gJ2xlZnQnIDogJ3JpZ2h0JztcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBlbGVtZW50c1tpXS5zdHlsZS50cmFuc2Zvcm1PcmlnaW4gPSBgJHt4T3JpZ2lufSAke3lPcmlnaW59YDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgcG9zaXRpb24gYW5kIHNpemUgb2YgdGhlIG92ZXJsYXkncyBzaXppbmcgY29udGFpbmVyLlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBkb2VzIG5vIG1lYXN1cmluZyBhbmQgYXBwbGllcyBubyBzdHlsZXMgc28gdGhhdCB3ZSBjYW4gY2hlYXBseSBjb21wdXRlIHRoZVxuICAgKiBib3VuZHMgZm9yIGFsbCBwb3NpdGlvbnMgYW5kIGNob29zZSB0aGUgYmVzdCBmaXQgYmFzZWQgb24gdGhlc2UgcmVzdWx0cy5cbiAgICovXG4gIHByaXZhdGUgX2NhbGN1bGF0ZUJvdW5kaW5nQm94UmVjdChvcmlnaW46IFBvaW50LCBwb3NpdGlvbjogQ29ubmVjdGVkUG9zaXRpb24pOiBCb3VuZGluZ0JveFJlY3Qge1xuICAgIGNvbnN0IHZpZXdwb3J0ID0gdGhpcy5fdmlld3BvcnRSZWN0O1xuICAgIGNvbnN0IGlzUnRsID0gdGhpcy5faXNSdGwoKTtcbiAgICBsZXQgaGVpZ2h0OiBudW1iZXIsIHRvcDogbnVtYmVyLCBib3R0b206IG51bWJlcjtcblxuICAgIGlmIChwb3NpdGlvbi5vdmVybGF5WSA9PT0gJ3RvcCcpIHtcbiAgICAgIC8vIE92ZXJsYXkgaXMgb3BlbmluZyBcImRvd253YXJkXCIgYW5kIHRodXMgaXMgYm91bmQgYnkgdGhlIGJvdHRvbSB2aWV3cG9ydCBlZGdlLlxuICAgICAgdG9wID0gb3JpZ2luLnk7XG4gICAgICBoZWlnaHQgPSB2aWV3cG9ydC5oZWlnaHQgLSB0b3AgKyB0aGlzLl92aWV3cG9ydE1hcmdpbjtcbiAgICB9IGVsc2UgaWYgKHBvc2l0aW9uLm92ZXJsYXlZID09PSAnYm90dG9tJykge1xuICAgICAgLy8gT3ZlcmxheSBpcyBvcGVuaW5nIFwidXB3YXJkXCIgYW5kIHRodXMgaXMgYm91bmQgYnkgdGhlIHRvcCB2aWV3cG9ydCBlZGdlLiBXZSBuZWVkIHRvIGFkZFxuICAgICAgLy8gdGhlIHZpZXdwb3J0IG1hcmdpbiBiYWNrIGluLCBiZWNhdXNlIHRoZSB2aWV3cG9ydCByZWN0IGlzIG5hcnJvd2VkIGRvd24gdG8gcmVtb3ZlIHRoZVxuICAgICAgLy8gbWFyZ2luLCB3aGVyZWFzIHRoZSBgb3JpZ2luYCBwb3NpdGlvbiBpcyBjYWxjdWxhdGVkIGJhc2VkIG9uIGl0cyBgQ2xpZW50UmVjdGAuXG4gICAgICBib3R0b20gPSB2aWV3cG9ydC5oZWlnaHQgLSBvcmlnaW4ueSArIHRoaXMuX3ZpZXdwb3J0TWFyZ2luICogMjtcbiAgICAgIGhlaWdodCA9IHZpZXdwb3J0LmhlaWdodCAtIGJvdHRvbSArIHRoaXMuX3ZpZXdwb3J0TWFyZ2luO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJZiBuZWl0aGVyIHRvcCBub3IgYm90dG9tLCBpdCBtZWFucyB0aGF0IHRoZSBvdmVybGF5IGlzIHZlcnRpY2FsbHkgY2VudGVyZWQgb24gdGhlXG4gICAgICAvLyBvcmlnaW4gcG9pbnQuIE5vdGUgdGhhdCB3ZSB3YW50IHRoZSBwb3NpdGlvbiByZWxhdGl2ZSB0byB0aGUgdmlld3BvcnQsIHJhdGhlciB0aGFuXG4gICAgICAvLyB0aGUgcGFnZSwgd2hpY2ggaXMgd2h5IHdlIGRvbid0IHVzZSBzb21ldGhpbmcgbGlrZSBgdmlld3BvcnQuYm90dG9tIC0gb3JpZ2luLnlgIGFuZFxuICAgICAgLy8gYG9yaWdpbi55IC0gdmlld3BvcnQudG9wYC5cbiAgICAgIGNvbnN0IHNtYWxsZXN0RGlzdGFuY2VUb1ZpZXdwb3J0RWRnZSA9XG4gICAgICAgICAgTWF0aC5taW4odmlld3BvcnQuYm90dG9tIC0gb3JpZ2luLnkgKyB2aWV3cG9ydC50b3AsIG9yaWdpbi55KTtcblxuICAgICAgY29uc3QgcHJldmlvdXNIZWlnaHQgPSB0aGlzLl9sYXN0Qm91bmRpbmdCb3hTaXplLmhlaWdodDtcblxuICAgICAgaGVpZ2h0ID0gc21hbGxlc3REaXN0YW5jZVRvVmlld3BvcnRFZGdlICogMjtcbiAgICAgIHRvcCA9IG9yaWdpbi55IC0gc21hbGxlc3REaXN0YW5jZVRvVmlld3BvcnRFZGdlO1xuXG4gICAgICBpZiAoaGVpZ2h0ID4gcHJldmlvdXNIZWlnaHQgJiYgIXRoaXMuX2lzSW5pdGlhbFJlbmRlciAmJiAhdGhpcy5fZ3Jvd0FmdGVyT3Blbikge1xuICAgICAgICB0b3AgPSBvcmlnaW4ueSAtIChwcmV2aW91c0hlaWdodCAvIDIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRoZSBvdmVybGF5IGlzIG9wZW5pbmcgJ3JpZ2h0LXdhcmQnICh0aGUgY29udGVudCBmbG93cyB0byB0aGUgcmlnaHQpLlxuICAgIGNvbnN0IGlzQm91bmRlZEJ5UmlnaHRWaWV3cG9ydEVkZ2UgPVxuICAgICAgICAocG9zaXRpb24ub3ZlcmxheVggPT09ICdzdGFydCcgJiYgIWlzUnRsKSB8fFxuICAgICAgICAocG9zaXRpb24ub3ZlcmxheVggPT09ICdlbmQnICYmIGlzUnRsKTtcblxuICAgIC8vIFRoZSBvdmVybGF5IGlzIG9wZW5pbmcgJ2xlZnQtd2FyZCcgKHRoZSBjb250ZW50IGZsb3dzIHRvIHRoZSBsZWZ0KS5cbiAgICBjb25zdCBpc0JvdW5kZWRCeUxlZnRWaWV3cG9ydEVkZ2UgPVxuICAgICAgICAocG9zaXRpb24ub3ZlcmxheVggPT09ICdlbmQnICYmICFpc1J0bCkgfHxcbiAgICAgICAgKHBvc2l0aW9uLm92ZXJsYXlYID09PSAnc3RhcnQnICYmIGlzUnRsKTtcblxuICAgIGxldCB3aWR0aDogbnVtYmVyLCBsZWZ0OiBudW1iZXIsIHJpZ2h0OiBudW1iZXI7XG5cbiAgICBpZiAoaXNCb3VuZGVkQnlMZWZ0Vmlld3BvcnRFZGdlKSB7XG4gICAgICByaWdodCA9IHZpZXdwb3J0LndpZHRoIC0gb3JpZ2luLnggKyB0aGlzLl92aWV3cG9ydE1hcmdpbjtcbiAgICAgIHdpZHRoID0gb3JpZ2luLnggLSB0aGlzLl92aWV3cG9ydE1hcmdpbjtcbiAgICB9IGVsc2UgaWYgKGlzQm91bmRlZEJ5UmlnaHRWaWV3cG9ydEVkZ2UpIHtcbiAgICAgIGxlZnQgPSBvcmlnaW4ueDtcbiAgICAgIHdpZHRoID0gdmlld3BvcnQucmlnaHQgLSBvcmlnaW4ueDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSWYgbmVpdGhlciBzdGFydCBub3IgZW5kLCBpdCBtZWFucyB0aGF0IHRoZSBvdmVybGF5IGlzIGhvcml6b250YWxseSBjZW50ZXJlZCBvbiB0aGVcbiAgICAgIC8vIG9yaWdpbiBwb2ludC4gTm90ZSB0aGF0IHdlIHdhbnQgdGhlIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSB2aWV3cG9ydCwgcmF0aGVyIHRoYW5cbiAgICAgIC8vIHRoZSBwYWdlLCB3aGljaCBpcyB3aHkgd2UgZG9uJ3QgdXNlIHNvbWV0aGluZyBsaWtlIGB2aWV3cG9ydC5yaWdodCAtIG9yaWdpbi54YCBhbmRcbiAgICAgIC8vIGBvcmlnaW4ueCAtIHZpZXdwb3J0LmxlZnRgLlxuICAgICAgY29uc3Qgc21hbGxlc3REaXN0YW5jZVRvVmlld3BvcnRFZGdlID1cbiAgICAgICAgICBNYXRoLm1pbih2aWV3cG9ydC5yaWdodCAtIG9yaWdpbi54ICsgdmlld3BvcnQubGVmdCwgb3JpZ2luLngpO1xuICAgICAgY29uc3QgcHJldmlvdXNXaWR0aCA9IHRoaXMuX2xhc3RCb3VuZGluZ0JveFNpemUud2lkdGg7XG5cbiAgICAgIHdpZHRoID0gc21hbGxlc3REaXN0YW5jZVRvVmlld3BvcnRFZGdlICogMjtcbiAgICAgIGxlZnQgPSBvcmlnaW4ueCAtIHNtYWxsZXN0RGlzdGFuY2VUb1ZpZXdwb3J0RWRnZTtcblxuICAgICAgaWYgKHdpZHRoID4gcHJldmlvdXNXaWR0aCAmJiAhdGhpcy5faXNJbml0aWFsUmVuZGVyICYmICF0aGlzLl9ncm93QWZ0ZXJPcGVuKSB7XG4gICAgICAgIGxlZnQgPSBvcmlnaW4ueCAtIChwcmV2aW91c1dpZHRoIC8gMik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHt0b3A6IHRvcCEsIGxlZnQ6IGxlZnQhLCBib3R0b206IGJvdHRvbSEsIHJpZ2h0OiByaWdodCEsIHdpZHRoLCBoZWlnaHR9O1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHBvc2l0aW9uIGFuZCBzaXplIG9mIHRoZSBvdmVybGF5J3Mgc2l6aW5nIHdyYXBwZXIuIFRoZSB3cmFwcGVyIGlzIHBvc2l0aW9uZWQgb24gdGhlXG4gICAqIG9yaWdpbidzIGNvbm5lY3Rpb24gcG9pbnQgYW5kIHN0ZXRjaGVzIHRvIHRoZSBib3VuZHMgb2YgdGhlIHZpZXdwb3J0LlxuICAgKlxuICAgKiBAcGFyYW0gb3JpZ2luIFRoZSBwb2ludCBvbiB0aGUgb3JpZ2luIGVsZW1lbnQgd2hlcmUgdGhlIG92ZXJsYXkgaXMgY29ubmVjdGVkLlxuICAgKiBAcGFyYW0gcG9zaXRpb24gVGhlIHBvc2l0aW9uIHByZWZlcmVuY2VcbiAgICovXG4gIHByaXZhdGUgX3NldEJvdW5kaW5nQm94U3R5bGVzKG9yaWdpbjogUG9pbnQsIHBvc2l0aW9uOiBDb25uZWN0ZWRQb3NpdGlvbik6IHZvaWQge1xuICAgIGNvbnN0IGJvdW5kaW5nQm94UmVjdCA9IHRoaXMuX2NhbGN1bGF0ZUJvdW5kaW5nQm94UmVjdChvcmlnaW4sIHBvc2l0aW9uKTtcblxuICAgIC8vIEl0J3Mgd2VpcmQgaWYgdGhlIG92ZXJsYXkgKmdyb3dzKiB3aGlsZSBzY3JvbGxpbmcsIHNvIHdlIHRha2UgdGhlIGxhc3Qgc2l6ZSBpbnRvIGFjY291bnRcbiAgICAvLyB3aGVuIGFwcGx5aW5nIGEgbmV3IHNpemUuXG4gICAgaWYgKCF0aGlzLl9pc0luaXRpYWxSZW5kZXIgJiYgIXRoaXMuX2dyb3dBZnRlck9wZW4pIHtcbiAgICAgIGJvdW5kaW5nQm94UmVjdC5oZWlnaHQgPSBNYXRoLm1pbihib3VuZGluZ0JveFJlY3QuaGVpZ2h0LCB0aGlzLl9sYXN0Qm91bmRpbmdCb3hTaXplLmhlaWdodCk7XG4gICAgICBib3VuZGluZ0JveFJlY3Qud2lkdGggPSBNYXRoLm1pbihib3VuZGluZ0JveFJlY3Qud2lkdGgsIHRoaXMuX2xhc3RCb3VuZGluZ0JveFNpemUud2lkdGgpO1xuICAgIH1cblxuICAgIGNvbnN0IHN0eWxlcyA9IHt9IGFzIENTU1N0eWxlRGVjbGFyYXRpb247XG5cbiAgICBpZiAodGhpcy5faGFzRXhhY3RQb3NpdGlvbigpKSB7XG4gICAgICBzdHlsZXMudG9wID0gc3R5bGVzLmxlZnQgPSAnMCc7XG4gICAgICBzdHlsZXMuYm90dG9tID0gc3R5bGVzLnJpZ2h0ID0gc3R5bGVzLm1heEhlaWdodCA9IHN0eWxlcy5tYXhXaWR0aCA9ICcnO1xuICAgICAgc3R5bGVzLndpZHRoID0gc3R5bGVzLmhlaWdodCA9ICcxMDAlJztcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgbWF4SGVpZ2h0ID0gdGhpcy5fb3ZlcmxheVJlZi5nZXRDb25maWcoKS5tYXhIZWlnaHQ7XG4gICAgICBjb25zdCBtYXhXaWR0aCA9IHRoaXMuX292ZXJsYXlSZWYuZ2V0Q29uZmlnKCkubWF4V2lkdGg7XG5cbiAgICAgIHN0eWxlcy5oZWlnaHQgPSBjb2VyY2VDc3NQaXhlbFZhbHVlKGJvdW5kaW5nQm94UmVjdC5oZWlnaHQpO1xuICAgICAgc3R5bGVzLnRvcCA9IGNvZXJjZUNzc1BpeGVsVmFsdWUoYm91bmRpbmdCb3hSZWN0LnRvcCk7XG4gICAgICBzdHlsZXMuYm90dG9tID0gY29lcmNlQ3NzUGl4ZWxWYWx1ZShib3VuZGluZ0JveFJlY3QuYm90dG9tKTtcbiAgICAgIHN0eWxlcy53aWR0aCA9IGNvZXJjZUNzc1BpeGVsVmFsdWUoYm91bmRpbmdCb3hSZWN0LndpZHRoKTtcbiAgICAgIHN0eWxlcy5sZWZ0ID0gY29lcmNlQ3NzUGl4ZWxWYWx1ZShib3VuZGluZ0JveFJlY3QubGVmdCk7XG4gICAgICBzdHlsZXMucmlnaHQgPSBjb2VyY2VDc3NQaXhlbFZhbHVlKGJvdW5kaW5nQm94UmVjdC5yaWdodCk7XG5cbiAgICAgIC8vIFB1c2ggdGhlIHBhbmUgY29udGVudCB0b3dhcmRzIHRoZSBwcm9wZXIgZGlyZWN0aW9uLlxuICAgICAgaWYgKHBvc2l0aW9uLm92ZXJsYXlYID09PSAnY2VudGVyJykge1xuICAgICAgICBzdHlsZXMuYWxpZ25JdGVtcyA9ICdjZW50ZXInO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3R5bGVzLmFsaWduSXRlbXMgPSBwb3NpdGlvbi5vdmVybGF5WCA9PT0gJ2VuZCcgPyAnZmxleC1lbmQnIDogJ2ZsZXgtc3RhcnQnO1xuICAgICAgfVxuXG4gICAgICBpZiAocG9zaXRpb24ub3ZlcmxheVkgPT09ICdjZW50ZXInKSB7XG4gICAgICAgIHN0eWxlcy5qdXN0aWZ5Q29udGVudCA9ICdjZW50ZXInO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3R5bGVzLmp1c3RpZnlDb250ZW50ID0gcG9zaXRpb24ub3ZlcmxheVkgPT09ICdib3R0b20nID8gJ2ZsZXgtZW5kJyA6ICdmbGV4LXN0YXJ0JztcbiAgICAgIH1cblxuICAgICAgaWYgKG1heEhlaWdodCkge1xuICAgICAgICBzdHlsZXMubWF4SGVpZ2h0ID0gY29lcmNlQ3NzUGl4ZWxWYWx1ZShtYXhIZWlnaHQpO1xuICAgICAgfVxuXG4gICAgICBpZiAobWF4V2lkdGgpIHtcbiAgICAgICAgc3R5bGVzLm1heFdpZHRoID0gY29lcmNlQ3NzUGl4ZWxWYWx1ZShtYXhXaWR0aCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5fbGFzdEJvdW5kaW5nQm94U2l6ZSA9IGJvdW5kaW5nQm94UmVjdDtcblxuICAgIGV4dGVuZFN0eWxlcyh0aGlzLl9ib3VuZGluZ0JveCEuc3R5bGUsIHN0eWxlcyk7XG4gIH1cblxuICAvKiogUmVzZXRzIHRoZSBzdHlsZXMgZm9yIHRoZSBib3VuZGluZyBib3ggc28gdGhhdCBhIG5ldyBwb3NpdGlvbmluZyBjYW4gYmUgY29tcHV0ZWQuICovXG4gIHByaXZhdGUgX3Jlc2V0Qm91bmRpbmdCb3hTdHlsZXMoKSB7XG4gICAgZXh0ZW5kU3R5bGVzKHRoaXMuX2JvdW5kaW5nQm94IS5zdHlsZSwge1xuICAgICAgdG9wOiAnMCcsXG4gICAgICBsZWZ0OiAnMCcsXG4gICAgICByaWdodDogJzAnLFxuICAgICAgYm90dG9tOiAnMCcsXG4gICAgICBoZWlnaHQ6ICcnLFxuICAgICAgd2lkdGg6ICcnLFxuICAgICAgYWxpZ25JdGVtczogJycsXG4gICAgICBqdXN0aWZ5Q29udGVudDogJycsXG4gICAgfSBhcyBDU1NTdHlsZURlY2xhcmF0aW9uKTtcbiAgfVxuXG4gIC8qKiBSZXNldHMgdGhlIHN0eWxlcyBmb3IgdGhlIG92ZXJsYXkgcGFuZSBzbyB0aGF0IGEgbmV3IHBvc2l0aW9uaW5nIGNhbiBiZSBjb21wdXRlZC4gKi9cbiAgcHJpdmF0ZSBfcmVzZXRPdmVybGF5RWxlbWVudFN0eWxlcygpIHtcbiAgICBleHRlbmRTdHlsZXModGhpcy5fcGFuZS5zdHlsZSwge1xuICAgICAgdG9wOiAnJyxcbiAgICAgIGxlZnQ6ICcnLFxuICAgICAgYm90dG9tOiAnJyxcbiAgICAgIHJpZ2h0OiAnJyxcbiAgICAgIHBvc2l0aW9uOiAnJyxcbiAgICAgIHRyYW5zZm9ybTogJycsXG4gICAgfSBhcyBDU1NTdHlsZURlY2xhcmF0aW9uKTtcbiAgfVxuXG4gIC8qKiBTZXRzIHBvc2l0aW9uaW5nIHN0eWxlcyB0byB0aGUgb3ZlcmxheSBlbGVtZW50LiAqL1xuICBwcml2YXRlIF9zZXRPdmVybGF5RWxlbWVudFN0eWxlcyhvcmlnaW5Qb2ludDogUG9pbnQsIHBvc2l0aW9uOiBDb25uZWN0ZWRQb3NpdGlvbik6IHZvaWQge1xuICAgIGNvbnN0IHN0eWxlcyA9IHt9IGFzIENTU1N0eWxlRGVjbGFyYXRpb247XG4gICAgY29uc3QgaGFzRXhhY3RQb3NpdGlvbiA9IHRoaXMuX2hhc0V4YWN0UG9zaXRpb24oKTtcbiAgICBjb25zdCBoYXNGbGV4aWJsZURpbWVuc2lvbnMgPSB0aGlzLl9oYXNGbGV4aWJsZURpbWVuc2lvbnM7XG4gICAgY29uc3QgY29uZmlnID0gdGhpcy5fb3ZlcmxheVJlZi5nZXRDb25maWcoKTtcblxuICAgIGlmIChoYXNFeGFjdFBvc2l0aW9uKSB7XG4gICAgICBjb25zdCBzY3JvbGxQb3NpdGlvbiA9IHRoaXMuX3ZpZXdwb3J0UnVsZXIuZ2V0Vmlld3BvcnRTY3JvbGxQb3NpdGlvbigpO1xuICAgICAgZXh0ZW5kU3R5bGVzKHN0eWxlcywgdGhpcy5fZ2V0RXhhY3RPdmVybGF5WShwb3NpdGlvbiwgb3JpZ2luUG9pbnQsIHNjcm9sbFBvc2l0aW9uKSk7XG4gICAgICBleHRlbmRTdHlsZXMoc3R5bGVzLCB0aGlzLl9nZXRFeGFjdE92ZXJsYXlYKHBvc2l0aW9uLCBvcmlnaW5Qb2ludCwgc2Nyb2xsUG9zaXRpb24pKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3R5bGVzLnBvc2l0aW9uID0gJ3N0YXRpYyc7XG4gICAgfVxuXG4gICAgLy8gVXNlIGEgdHJhbnNmb3JtIHRvIGFwcGx5IHRoZSBvZmZzZXRzLiBXZSBkbyB0aGlzIGJlY2F1c2UgdGhlIGBjZW50ZXJgIHBvc2l0aW9ucyByZWx5IG9uXG4gICAgLy8gYmVpbmcgaW4gdGhlIG5vcm1hbCBmbGV4IGZsb3cgYW5kIHNldHRpbmcgYSBgdG9wYCAvIGBsZWZ0YCBhdCBhbGwgd2lsbCBjb21wbGV0ZWx5IHRocm93XG4gICAgLy8gb2ZmIHRoZSBwb3NpdGlvbi4gV2UgYWxzbyBjYW4ndCB1c2UgbWFyZ2lucywgYmVjYXVzZSB0aGV5IHdvbid0IGhhdmUgYW4gZWZmZWN0IGluIHNvbWVcbiAgICAvLyBjYXNlcyB3aGVyZSB0aGUgZWxlbWVudCBkb2Vzbid0IGhhdmUgYW55dGhpbmcgdG8gXCJwdXNoIG9mZiBvZlwiLiBGaW5hbGx5LCB0aGlzIHdvcmtzXG4gICAgLy8gYmV0dGVyIGJvdGggd2l0aCBmbGV4aWJsZSBhbmQgbm9uLWZsZXhpYmxlIHBvc2l0aW9uaW5nLlxuICAgIGxldCB0cmFuc2Zvcm1TdHJpbmcgPSAnJztcbiAgICBsZXQgb2Zmc2V0WCA9IHRoaXMuX2dldE9mZnNldChwb3NpdGlvbiwgJ3gnKTtcbiAgICBsZXQgb2Zmc2V0WSA9IHRoaXMuX2dldE9mZnNldChwb3NpdGlvbiwgJ3knKTtcblxuICAgIGlmIChvZmZzZXRYKSB7XG4gICAgICB0cmFuc2Zvcm1TdHJpbmcgKz0gYHRyYW5zbGF0ZVgoJHtvZmZzZXRYfXB4KSBgO1xuICAgIH1cblxuICAgIGlmIChvZmZzZXRZKSB7XG4gICAgICB0cmFuc2Zvcm1TdHJpbmcgKz0gYHRyYW5zbGF0ZVkoJHtvZmZzZXRZfXB4KWA7XG4gICAgfVxuXG4gICAgc3R5bGVzLnRyYW5zZm9ybSA9IHRyYW5zZm9ybVN0cmluZy50cmltKCk7XG5cbiAgICAvLyBJZiBhIG1heFdpZHRoIG9yIG1heEhlaWdodCBpcyBzcGVjaWZpZWQgb24gdGhlIG92ZXJsYXksIHdlIHJlbW92ZSB0aGVtLiBXZSBkbyB0aGlzIGJlY2F1c2VcbiAgICAvLyB3ZSBuZWVkIHRoZXNlIHZhbHVlcyB0byBib3RoIGJlIHNldCB0byBcIjEwMCVcIiBmb3IgdGhlIGF1dG9tYXRpYyBmbGV4aWJsZSBzaXppbmcgdG8gd29yay5cbiAgICAvLyBUaGUgbWF4SGVpZ2h0IGFuZCBtYXhXaWR0aCBhcmUgc2V0IG9uIHRoZSBib3VuZGluZ0JveCBpbiBvcmRlciB0byBlbmZvcmNlIHRoZSBjb25zdHJhaW50LlxuICAgIC8vIE5vdGUgdGhhdCB0aGlzIGRvZXNuJ3QgYXBwbHkgd2hlbiB3ZSBoYXZlIGFuIGV4YWN0IHBvc2l0aW9uLCBpbiB3aGljaCBjYXNlIHdlIGRvIHdhbnQgdG9cbiAgICAvLyBhcHBseSB0aGVtIGJlY2F1c2UgdGhleSdsbCBiZSBjbGVhcmVkIGZyb20gdGhlIGJvdW5kaW5nIGJveC5cbiAgICBpZiAoY29uZmlnLm1heEhlaWdodCkge1xuICAgICAgaWYgKGhhc0V4YWN0UG9zaXRpb24pIHtcbiAgICAgICAgc3R5bGVzLm1heEhlaWdodCA9IGNvZXJjZUNzc1BpeGVsVmFsdWUoY29uZmlnLm1heEhlaWdodCk7XG4gICAgICB9IGVsc2UgaWYgKGhhc0ZsZXhpYmxlRGltZW5zaW9ucykge1xuICAgICAgICBzdHlsZXMubWF4SGVpZ2h0ID0gJyc7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNvbmZpZy5tYXhXaWR0aCkge1xuICAgICAgaWYgKGhhc0V4YWN0UG9zaXRpb24pIHtcbiAgICAgICAgc3R5bGVzLm1heFdpZHRoID0gY29lcmNlQ3NzUGl4ZWxWYWx1ZShjb25maWcubWF4V2lkdGgpO1xuICAgICAgfSBlbHNlIGlmIChoYXNGbGV4aWJsZURpbWVuc2lvbnMpIHtcbiAgICAgICAgc3R5bGVzLm1heFdpZHRoID0gJyc7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZXh0ZW5kU3R5bGVzKHRoaXMuX3BhbmUuc3R5bGUsIHN0eWxlcyk7XG4gIH1cblxuICAvKiogR2V0cyB0aGUgZXhhY3QgdG9wL2JvdHRvbSBmb3IgdGhlIG92ZXJsYXkgd2hlbiBub3QgdXNpbmcgZmxleGlibGUgc2l6aW5nIG9yIHdoZW4gcHVzaGluZy4gKi9cbiAgcHJpdmF0ZSBfZ2V0RXhhY3RPdmVybGF5WShwb3NpdGlvbjogQ29ubmVjdGVkUG9zaXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ2luUG9pbnQ6IFBvaW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjcm9sbFBvc2l0aW9uOiBWaWV3cG9ydFNjcm9sbFBvc2l0aW9uKSB7XG4gICAgLy8gUmVzZXQgYW55IGV4aXN0aW5nIHN0eWxlcy4gVGhpcyBpcyBuZWNlc3NhcnkgaW4gY2FzZSB0aGVcbiAgICAvLyBwcmVmZXJyZWQgcG9zaXRpb24gaGFzIGNoYW5nZWQgc2luY2UgdGhlIGxhc3QgYGFwcGx5YC5cbiAgICBsZXQgc3R5bGVzID0ge3RvcDogJycsIGJvdHRvbTogJyd9IGFzIENTU1N0eWxlRGVjbGFyYXRpb247XG4gICAgbGV0IG92ZXJsYXlQb2ludCA9IHRoaXMuX2dldE92ZXJsYXlQb2ludChvcmlnaW5Qb2ludCwgdGhpcy5fb3ZlcmxheVJlY3QsIHBvc2l0aW9uKTtcblxuICAgIGlmICh0aGlzLl9pc1B1c2hlZCkge1xuICAgICAgb3ZlcmxheVBvaW50ID0gdGhpcy5fcHVzaE92ZXJsYXlPblNjcmVlbihvdmVybGF5UG9pbnQsIHRoaXMuX292ZXJsYXlSZWN0LCBzY3JvbGxQb3NpdGlvbik7XG4gICAgfVxuXG4gICAgbGV0IHZpcnR1YWxLZXlib2FyZE9mZnNldCA9XG4gICAgICAgIHRoaXMuX292ZXJsYXlDb250YWluZXIuZ2V0Q29udGFpbmVyRWxlbWVudCgpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLnRvcDtcblxuICAgIC8vIE5vcm1hbGx5IHRoaXMgd291bGQgYmUgemVybywgaG93ZXZlciB3aGVuIHRoZSBvdmVybGF5IGlzIGF0dGFjaGVkIHRvIGFuIGlucHV0IChlLmcuIGluIGFuXG4gICAgLy8gYXV0b2NvbXBsZXRlKSwgbW9iaWxlIGJyb3dzZXJzIHdpbGwgc2hpZnQgZXZlcnl0aGluZyBpbiBvcmRlciB0byBwdXQgdGhlIGlucHV0IGluIHRoZSBtaWRkbGVcbiAgICAvLyBvZiB0aGUgc2NyZWVuIGFuZCB0byBtYWtlIHNwYWNlIGZvciB0aGUgdmlydHVhbCBrZXlib2FyZC4gV2UgbmVlZCB0byBhY2NvdW50IGZvciB0aGlzIG9mZnNldCxcbiAgICAvLyBvdGhlcndpc2Ugb3VyIHBvc2l0aW9uaW5nIHdpbGwgYmUgdGhyb3duIG9mZi5cbiAgICBvdmVybGF5UG9pbnQueSAtPSB2aXJ0dWFsS2V5Ym9hcmRPZmZzZXQ7XG5cbiAgICAvLyBXZSB3YW50IHRvIHNldCBlaXRoZXIgYHRvcGAgb3IgYGJvdHRvbWAgYmFzZWQgb24gd2hldGhlciB0aGUgb3ZlcmxheSB3YW50cyB0byBhcHBlYXJcbiAgICAvLyBhYm92ZSBvciBiZWxvdyB0aGUgb3JpZ2luIGFuZCB0aGUgZGlyZWN0aW9uIGluIHdoaWNoIHRoZSBlbGVtZW50IHdpbGwgZXhwYW5kLlxuICAgIGlmIChwb3NpdGlvbi5vdmVybGF5WSA9PT0gJ2JvdHRvbScpIHtcbiAgICAgIC8vIFdoZW4gdXNpbmcgYGJvdHRvbWAsIHdlIGFkanVzdCB0aGUgeSBwb3NpdGlvbiBzdWNoIHRoYXQgaXQgaXMgdGhlIGRpc3RhbmNlXG4gICAgICAvLyBmcm9tIHRoZSBib3R0b20gb2YgdGhlIHZpZXdwb3J0IHJhdGhlciB0aGFuIHRoZSB0b3AuXG4gICAgICBjb25zdCBkb2N1bWVudEhlaWdodCA9IHRoaXMuX2RvY3VtZW50LmRvY3VtZW50RWxlbWVudCEuY2xpZW50SGVpZ2h0O1xuICAgICAgc3R5bGVzLmJvdHRvbSA9IGAke2RvY3VtZW50SGVpZ2h0IC0gKG92ZXJsYXlQb2ludC55ICsgdGhpcy5fb3ZlcmxheVJlY3QuaGVpZ2h0KX1weGA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0eWxlcy50b3AgPSBjb2VyY2VDc3NQaXhlbFZhbHVlKG92ZXJsYXlQb2ludC55KTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3R5bGVzO1xuICB9XG5cbiAgLyoqIEdldHMgdGhlIGV4YWN0IGxlZnQvcmlnaHQgZm9yIHRoZSBvdmVybGF5IHdoZW4gbm90IHVzaW5nIGZsZXhpYmxlIHNpemluZyBvciB3aGVuIHB1c2hpbmcuICovXG4gIHByaXZhdGUgX2dldEV4YWN0T3ZlcmxheVgocG9zaXRpb246IENvbm5lY3RlZFBvc2l0aW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yaWdpblBvaW50OiBQb2ludCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY3JvbGxQb3NpdGlvbjogVmlld3BvcnRTY3JvbGxQb3NpdGlvbikge1xuICAgIC8vIFJlc2V0IGFueSBleGlzdGluZyBzdHlsZXMuIFRoaXMgaXMgbmVjZXNzYXJ5IGluIGNhc2UgdGhlIHByZWZlcnJlZCBwb3NpdGlvbiBoYXNcbiAgICAvLyBjaGFuZ2VkIHNpbmNlIHRoZSBsYXN0IGBhcHBseWAuXG4gICAgbGV0IHN0eWxlcyA9IHtsZWZ0OiAnJywgcmlnaHQ6ICcnfSBhcyBDU1NTdHlsZURlY2xhcmF0aW9uO1xuICAgIGxldCBvdmVybGF5UG9pbnQgPSB0aGlzLl9nZXRPdmVybGF5UG9pbnQob3JpZ2luUG9pbnQsIHRoaXMuX292ZXJsYXlSZWN0LCBwb3NpdGlvbik7XG5cbiAgICBpZiAodGhpcy5faXNQdXNoZWQpIHtcbiAgICAgIG92ZXJsYXlQb2ludCA9IHRoaXMuX3B1c2hPdmVybGF5T25TY3JlZW4ob3ZlcmxheVBvaW50LCB0aGlzLl9vdmVybGF5UmVjdCwgc2Nyb2xsUG9zaXRpb24pO1xuICAgIH1cblxuICAgIC8vIFdlIHdhbnQgdG8gc2V0IGVpdGhlciBgbGVmdGAgb3IgYHJpZ2h0YCBiYXNlZCBvbiB3aGV0aGVyIHRoZSBvdmVybGF5IHdhbnRzIHRvIGFwcGVhciBcImJlZm9yZVwiXG4gICAgLy8gb3IgXCJhZnRlclwiIHRoZSBvcmlnaW4sIHdoaWNoIGRldGVybWluZXMgdGhlIGRpcmVjdGlvbiBpbiB3aGljaCB0aGUgZWxlbWVudCB3aWxsIGV4cGFuZC5cbiAgICAvLyBGb3IgdGhlIGhvcml6b250YWwgYXhpcywgdGhlIG1lYW5pbmcgb2YgXCJiZWZvcmVcIiBhbmQgXCJhZnRlclwiIGNoYW5nZSBiYXNlZCBvbiB3aGV0aGVyIHRoZVxuICAgIC8vIHBhZ2UgaXMgaW4gUlRMIG9yIExUUi5cbiAgICBsZXQgaG9yaXpvbnRhbFN0eWxlUHJvcGVydHk6ICdsZWZ0JyB8ICdyaWdodCc7XG5cbiAgICBpZiAodGhpcy5faXNSdGwoKSkge1xuICAgICAgaG9yaXpvbnRhbFN0eWxlUHJvcGVydHkgPSBwb3NpdGlvbi5vdmVybGF5WCA9PT0gJ2VuZCcgPyAnbGVmdCcgOiAncmlnaHQnO1xuICAgIH0gZWxzZSB7XG4gICAgICBob3Jpem9udGFsU3R5bGVQcm9wZXJ0eSA9IHBvc2l0aW9uLm92ZXJsYXlYID09PSAnZW5kJyA/ICdyaWdodCcgOiAnbGVmdCc7XG4gICAgfVxuXG4gICAgLy8gV2hlbiB3ZSdyZSBzZXR0aW5nIGByaWdodGAsIHdlIGFkanVzdCB0aGUgeCBwb3NpdGlvbiBzdWNoIHRoYXQgaXQgaXMgdGhlIGRpc3RhbmNlXG4gICAgLy8gZnJvbSB0aGUgcmlnaHQgZWRnZSBvZiB0aGUgdmlld3BvcnQgcmF0aGVyIHRoYW4gdGhlIGxlZnQgZWRnZS5cbiAgICBpZiAoaG9yaXpvbnRhbFN0eWxlUHJvcGVydHkgPT09ICdyaWdodCcpIHtcbiAgICAgIGNvbnN0IGRvY3VtZW50V2lkdGggPSB0aGlzLl9kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQhLmNsaWVudFdpZHRoO1xuICAgICAgc3R5bGVzLnJpZ2h0ID0gYCR7ZG9jdW1lbnRXaWR0aCAtIChvdmVybGF5UG9pbnQueCArIHRoaXMuX292ZXJsYXlSZWN0LndpZHRoKX1weGA7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0eWxlcy5sZWZ0ID0gY29lcmNlQ3NzUGl4ZWxWYWx1ZShvdmVybGF5UG9pbnQueCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHN0eWxlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSB2aWV3IHByb3BlcnRpZXMgb2YgdGhlIHRyaWdnZXIgYW5kIG92ZXJsYXksIGluY2x1ZGluZyB3aGV0aGVyIHRoZXkgYXJlIGNsaXBwZWRcbiAgICogb3IgY29tcGxldGVseSBvdXRzaWRlIHRoZSB2aWV3IG9mIGFueSBvZiB0aGUgc3RyYXRlZ3kncyBzY3JvbGxhYmxlcy5cbiAgICovXG4gIHByaXZhdGUgX2dldFNjcm9sbFZpc2liaWxpdHkoKTogU2Nyb2xsaW5nVmlzaWJpbGl0eSB7XG4gICAgLy8gTm90ZTogbmVlZHMgZnJlc2ggcmVjdHMgc2luY2UgdGhlIHBvc2l0aW9uIGNvdWxkJ3ZlIGNoYW5nZWQuXG4gICAgY29uc3Qgb3JpZ2luQm91bmRzID0gdGhpcy5fZ2V0T3JpZ2luUmVjdCgpO1xuICAgIGNvbnN0IG92ZXJsYXlCb3VuZHMgPSAgdGhpcy5fcGFuZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuICAgIC8vIFRPRE8oamVsYm91cm4pOiBpbnN0ZWFkIG9mIG5lZWRpbmcgYWxsIG9mIHRoZSBjbGllbnQgcmVjdHMgZm9yIHRoZXNlIHNjcm9sbGluZyBjb250YWluZXJzXG4gICAgLy8gZXZlcnkgdGltZSwgd2Ugc2hvdWxkIGJlIGFibGUgdG8gdXNlIHRoZSBzY3JvbGxUb3Agb2YgdGhlIGNvbnRhaW5lcnMgaWYgdGhlIHNpemUgb2YgdGhvc2VcbiAgICAvLyBjb250YWluZXJzIGhhc24ndCBjaGFuZ2VkLlxuICAgIGNvbnN0IHNjcm9sbENvbnRhaW5lckJvdW5kcyA9IHRoaXMuX3Njcm9sbGFibGVzLm1hcChzY3JvbGxhYmxlID0+IHtcbiAgICAgIHJldHVybiBzY3JvbGxhYmxlLmdldEVsZW1lbnRSZWYoKS5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGlzT3JpZ2luQ2xpcHBlZDogaXNFbGVtZW50Q2xpcHBlZEJ5U2Nyb2xsaW5nKG9yaWdpbkJvdW5kcywgc2Nyb2xsQ29udGFpbmVyQm91bmRzKSxcbiAgICAgIGlzT3JpZ2luT3V0c2lkZVZpZXc6IGlzRWxlbWVudFNjcm9sbGVkT3V0c2lkZVZpZXcob3JpZ2luQm91bmRzLCBzY3JvbGxDb250YWluZXJCb3VuZHMpLFxuICAgICAgaXNPdmVybGF5Q2xpcHBlZDogaXNFbGVtZW50Q2xpcHBlZEJ5U2Nyb2xsaW5nKG92ZXJsYXlCb3VuZHMsIHNjcm9sbENvbnRhaW5lckJvdW5kcyksXG4gICAgICBpc092ZXJsYXlPdXRzaWRlVmlldzogaXNFbGVtZW50U2Nyb2xsZWRPdXRzaWRlVmlldyhvdmVybGF5Qm91bmRzLCBzY3JvbGxDb250YWluZXJCb3VuZHMpLFxuICAgIH07XG4gIH1cblxuICAvKiogU3VidHJhY3RzIHRoZSBhbW91bnQgdGhhdCBhbiBlbGVtZW50IGlzIG92ZXJmbG93aW5nIG9uIGFuIGF4aXMgZnJvbSBpdHMgbGVuZ3RoLiAqL1xuICBwcml2YXRlIF9zdWJ0cmFjdE92ZXJmbG93cyhsZW5ndGg6IG51bWJlciwgLi4ub3ZlcmZsb3dzOiBudW1iZXJbXSk6IG51bWJlciB7XG4gICAgcmV0dXJuIG92ZXJmbG93cy5yZWR1Y2UoKGN1cnJlbnRWYWx1ZTogbnVtYmVyLCBjdXJyZW50T3ZlcmZsb3c6IG51bWJlcikgPT4ge1xuICAgICAgcmV0dXJuIGN1cnJlbnRWYWx1ZSAtIE1hdGgubWF4KGN1cnJlbnRPdmVyZmxvdywgMCk7XG4gICAgfSwgbGVuZ3RoKTtcbiAgfVxuXG4gIC8qKiBOYXJyb3dzIHRoZSBnaXZlbiB2aWV3cG9ydCByZWN0IGJ5IHRoZSBjdXJyZW50IF92aWV3cG9ydE1hcmdpbi4gKi9cbiAgcHJpdmF0ZSBfZ2V0TmFycm93ZWRWaWV3cG9ydFJlY3QoKTogQ2xpZW50UmVjdCB7XG4gICAgLy8gV2UgcmVjYWxjdWxhdGUgdGhlIHZpZXdwb3J0IHJlY3QgaGVyZSBvdXJzZWx2ZXMsIHJhdGhlciB0aGFuIHVzaW5nIHRoZSBWaWV3cG9ydFJ1bGVyLFxuICAgIC8vIGJlY2F1c2Ugd2Ugd2FudCB0byB1c2UgdGhlIGBjbGllbnRXaWR0aGAgYW5kIGBjbGllbnRIZWlnaHRgIGFzIHRoZSBiYXNlLiBUaGUgZGlmZmVyZW5jZVxuICAgIC8vIGJlaW5nIHRoYXQgdGhlIGNsaWVudCBwcm9wZXJ0aWVzIGRvbid0IGluY2x1ZGUgdGhlIHNjcm9sbGJhciwgYXMgb3Bwb3NlZCB0byBgaW5uZXJXaWR0aGBcbiAgICAvLyBhbmQgYGlubmVySGVpZ2h0YCB0aGF0IGRvLiBUaGlzIGlzIG5lY2Vzc2FyeSwgYmVjYXVzZSB0aGUgb3ZlcmxheSBjb250YWluZXIgdXNlc1xuICAgIC8vIDEwMCUgYHdpZHRoYCBhbmQgYGhlaWdodGAgd2hpY2ggZG9uJ3QgaW5jbHVkZSB0aGUgc2Nyb2xsYmFyIGVpdGhlci5cbiAgICBjb25zdCB3aWR0aCA9IHRoaXMuX2RvY3VtZW50LmRvY3VtZW50RWxlbWVudCEuY2xpZW50V2lkdGg7XG4gICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5fZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50IS5jbGllbnRIZWlnaHQ7XG4gICAgY29uc3Qgc2Nyb2xsUG9zaXRpb24gPSB0aGlzLl92aWV3cG9ydFJ1bGVyLmdldFZpZXdwb3J0U2Nyb2xsUG9zaXRpb24oKTtcblxuICAgIHJldHVybiB7XG4gICAgICB0b3A6ICAgIHNjcm9sbFBvc2l0aW9uLnRvcCArIHRoaXMuX3ZpZXdwb3J0TWFyZ2luLFxuICAgICAgbGVmdDogICBzY3JvbGxQb3NpdGlvbi5sZWZ0ICsgdGhpcy5fdmlld3BvcnRNYXJnaW4sXG4gICAgICByaWdodDogIHNjcm9sbFBvc2l0aW9uLmxlZnQgKyB3aWR0aCAtIHRoaXMuX3ZpZXdwb3J0TWFyZ2luLFxuICAgICAgYm90dG9tOiBzY3JvbGxQb3NpdGlvbi50b3AgKyBoZWlnaHQgLSB0aGlzLl92aWV3cG9ydE1hcmdpbixcbiAgICAgIHdpZHRoOiAgd2lkdGggIC0gKDIgKiB0aGlzLl92aWV3cG9ydE1hcmdpbiksXG4gICAgICBoZWlnaHQ6IGhlaWdodCAtICgyICogdGhpcy5fdmlld3BvcnRNYXJnaW4pLFxuICAgIH07XG4gIH1cblxuICAvKiogV2hldGhlciB0aGUgd2UncmUgZGVhbGluZyB3aXRoIGFuIFJUTCBjb250ZXh0ICovXG4gIHByaXZhdGUgX2lzUnRsKCkge1xuICAgIHJldHVybiB0aGlzLl9vdmVybGF5UmVmLmdldERpcmVjdGlvbigpID09PSAncnRsJztcbiAgfVxuXG4gIC8qKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlIG92ZXJsYXkgdXNlcyBleGFjdCBvciBmbGV4aWJsZSBwb3NpdGlvbmluZy4gKi9cbiAgcHJpdmF0ZSBfaGFzRXhhY3RQb3NpdGlvbigpIHtcbiAgICByZXR1cm4gIXRoaXMuX2hhc0ZsZXhpYmxlRGltZW5zaW9ucyB8fCB0aGlzLl9pc1B1c2hlZDtcbiAgfVxuXG4gIC8qKiBSZXRyaWV2ZXMgdGhlIG9mZnNldCBvZiBhIHBvc2l0aW9uIGFsb25nIHRoZSB4IG9yIHkgYXhpcy4gKi9cbiAgcHJpdmF0ZSBfZ2V0T2Zmc2V0KHBvc2l0aW9uOiBDb25uZWN0ZWRQb3NpdGlvbiwgYXhpczogJ3gnIHwgJ3knKSB7XG4gICAgaWYgKGF4aXMgPT09ICd4Jykge1xuICAgICAgLy8gV2UgZG9uJ3QgZG8gc29tZXRoaW5nIGxpa2UgYHBvc2l0aW9uWydvZmZzZXQnICsgYXhpc11gIGluXG4gICAgICAvLyBvcmRlciB0byBhdm9pZCBicmVraW5nIG1pbmlmaWVycyB0aGF0IHJlbmFtZSBwcm9wZXJ0aWVzLlxuICAgICAgcmV0dXJuIHBvc2l0aW9uLm9mZnNldFggPT0gbnVsbCA/IHRoaXMuX29mZnNldFggOiBwb3NpdGlvbi5vZmZzZXRYO1xuICAgIH1cblxuICAgIHJldHVybiBwb3NpdGlvbi5vZmZzZXRZID09IG51bGwgPyB0aGlzLl9vZmZzZXRZIDogcG9zaXRpb24ub2Zmc2V0WTtcbiAgfVxuXG4gIC8qKiBWYWxpZGF0ZXMgdGhhdCB0aGUgY3VycmVudCBwb3NpdGlvbiBtYXRjaCB0aGUgZXhwZWN0ZWQgdmFsdWVzLiAqL1xuICBwcml2YXRlIF92YWxpZGF0ZVBvc2l0aW9ucygpOiB2b2lkIHtcbiAgICBpZiAodHlwZW9mIG5nRGV2TW9kZSA9PT0gJ3VuZGVmaW5lZCcgfHwgbmdEZXZNb2RlKSB7XG4gICAgICBpZiAoIXRoaXMuX3ByZWZlcnJlZFBvc2l0aW9ucy5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgRXJyb3IoJ0ZsZXhpYmxlQ29ubmVjdGVkUG9zaXRpb25TdHJhdGVneTogQXQgbGVhc3Qgb25lIHBvc2l0aW9uIGlzIHJlcXVpcmVkLicpO1xuICAgICAgfVxuXG4gICAgICAvLyBUT0RPKGNyaXNiZXRvKTogcmVtb3ZlIHRoZXNlIG9uY2UgQW5ndWxhcidzIHRlbXBsYXRlIHR5cGVcbiAgICAgIC8vIGNoZWNraW5nIGlzIGFkdmFuY2VkIGVub3VnaCB0byBjYXRjaCB0aGVzZSBjYXNlcy5cbiAgICAgIHRoaXMuX3ByZWZlcnJlZFBvc2l0aW9ucy5mb3JFYWNoKHBhaXIgPT4ge1xuICAgICAgICB2YWxpZGF0ZUhvcml6b250YWxQb3NpdGlvbignb3JpZ2luWCcsIHBhaXIub3JpZ2luWCk7XG4gICAgICAgIHZhbGlkYXRlVmVydGljYWxQb3NpdGlvbignb3JpZ2luWScsIHBhaXIub3JpZ2luWSk7XG4gICAgICAgIHZhbGlkYXRlSG9yaXpvbnRhbFBvc2l0aW9uKCdvdmVybGF5WCcsIHBhaXIub3ZlcmxheVgpO1xuICAgICAgICB2YWxpZGF0ZVZlcnRpY2FsUG9zaXRpb24oJ292ZXJsYXlZJywgcGFpci5vdmVybGF5WSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKiogQWRkcyBhIHNpbmdsZSBDU1MgY2xhc3Mgb3IgYW4gYXJyYXkgb2YgY2xhc3NlcyBvbiB0aGUgb3ZlcmxheSBwYW5lbC4gKi9cbiAgcHJpdmF0ZSBfYWRkUGFuZWxDbGFzc2VzKGNzc0NsYXNzZXM6IHN0cmluZyB8IHN0cmluZ1tdKSB7XG4gICAgaWYgKHRoaXMuX3BhbmUpIHtcbiAgICAgIGNvZXJjZUFycmF5KGNzc0NsYXNzZXMpLmZvckVhY2goY3NzQ2xhc3MgPT4ge1xuICAgICAgICBpZiAoY3NzQ2xhc3MgIT09ICcnICYmIHRoaXMuX2FwcGxpZWRQYW5lbENsYXNzZXMuaW5kZXhPZihjc3NDbGFzcykgPT09IC0xKSB7XG4gICAgICAgICAgdGhpcy5fYXBwbGllZFBhbmVsQ2xhc3Nlcy5wdXNoKGNzc0NsYXNzKTtcbiAgICAgICAgICB0aGlzLl9wYW5lLmNsYXNzTGlzdC5hZGQoY3NzQ2xhc3MpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKiogQ2xlYXJzIHRoZSBjbGFzc2VzIHRoYXQgdGhlIHBvc2l0aW9uIHN0cmF0ZWd5IGhhcyBhcHBsaWVkIGZyb20gdGhlIG92ZXJsYXkgcGFuZWwuICovXG4gIHByaXZhdGUgX2NsZWFyUGFuZWxDbGFzc2VzKCkge1xuICAgIGlmICh0aGlzLl9wYW5lKSB7XG4gICAgICB0aGlzLl9hcHBsaWVkUGFuZWxDbGFzc2VzLmZvckVhY2goY3NzQ2xhc3MgPT4ge1xuICAgICAgICB0aGlzLl9wYW5lLmNsYXNzTGlzdC5yZW1vdmUoY3NzQ2xhc3MpO1xuICAgICAgfSk7XG4gICAgICB0aGlzLl9hcHBsaWVkUGFuZWxDbGFzc2VzID0gW107XG4gICAgfVxuICB9XG5cbiAgLyoqIFJldHVybnMgdGhlIENsaWVudFJlY3Qgb2YgdGhlIGN1cnJlbnQgb3JpZ2luLiAqL1xuICBwcml2YXRlIF9nZXRPcmlnaW5SZWN0KCk6IENsaWVudFJlY3Qge1xuICAgIGNvbnN0IG9yaWdpbiA9IHRoaXMuX29yaWdpbjtcblxuICAgIGlmIChvcmlnaW4gaW5zdGFuY2VvZiBFbGVtZW50UmVmKSB7XG4gICAgICByZXR1cm4gb3JpZ2luLm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIEVsZW1lbnQgc28gU1ZHIGVsZW1lbnRzIGFyZSBhbHNvIHN1cHBvcnRlZC5cbiAgICBpZiAob3JpZ2luIGluc3RhbmNlb2YgRWxlbWVudCkge1xuICAgICAgcmV0dXJuIG9yaWdpbi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICB9XG5cbiAgICBjb25zdCB3aWR0aCA9IG9yaWdpbi53aWR0aCB8fCAwO1xuICAgIGNvbnN0IGhlaWdodCA9IG9yaWdpbi5oZWlnaHQgfHwgMDtcblxuICAgIC8vIElmIHRoZSBvcmlnaW4gaXMgYSBwb2ludCwgcmV0dXJuIGEgY2xpZW50IHJlY3QgYXMgaWYgaXQgd2FzIGEgMHgwIGVsZW1lbnQgYXQgdGhlIHBvaW50LlxuICAgIHJldHVybiB7XG4gICAgICB0b3A6IG9yaWdpbi55LFxuICAgICAgYm90dG9tOiBvcmlnaW4ueSArIGhlaWdodCxcbiAgICAgIGxlZnQ6IG9yaWdpbi54LFxuICAgICAgcmlnaHQ6IG9yaWdpbi54ICsgd2lkdGgsXG4gICAgICBoZWlnaHQsXG4gICAgICB3aWR0aFxuICAgIH07XG4gIH1cbn1cblxuLyoqIEEgc2ltcGxlICh4LCB5KSBjb29yZGluYXRlLiAqL1xuaW50ZXJmYWNlIFBvaW50IHtcbiAgeDogbnVtYmVyO1xuICB5OiBudW1iZXI7XG59XG5cbi8qKiBSZWNvcmQgb2YgbWVhc3VyZW1lbnRzIGZvciBob3cgYW4gb3ZlcmxheSAoYXQgYSBnaXZlbiBwb3NpdGlvbikgZml0cyBpbnRvIHRoZSB2aWV3cG9ydC4gKi9cbmludGVyZmFjZSBPdmVybGF5Rml0IHtcbiAgLyoqIFdoZXRoZXIgdGhlIG92ZXJsYXkgZml0cyBjb21wbGV0ZWx5IGluIHRoZSB2aWV3cG9ydC4gKi9cbiAgaXNDb21wbGV0ZWx5V2l0aGluVmlld3BvcnQ6IGJvb2xlYW47XG5cbiAgLyoqIFdoZXRoZXIgdGhlIG92ZXJsYXkgZml0cyBpbiB0aGUgdmlld3BvcnQgb24gdGhlIHktYXhpcy4gKi9cbiAgZml0c0luVmlld3BvcnRWZXJ0aWNhbGx5OiBib29sZWFuO1xuXG4gIC8qKiBXaGV0aGVyIHRoZSBvdmVybGF5IGZpdHMgaW4gdGhlIHZpZXdwb3J0IG9uIHRoZSB4LWF4aXMuICovXG4gIGZpdHNJblZpZXdwb3J0SG9yaXpvbnRhbGx5OiBib29sZWFuO1xuXG4gIC8qKiBUaGUgdG90YWwgdmlzaWJsZSBhcmVhIChpbiBweF4yKSBvZiB0aGUgb3ZlcmxheSBpbnNpZGUgdGhlIHZpZXdwb3J0LiAqL1xuICB2aXNpYmxlQXJlYTogbnVtYmVyO1xufVxuXG4vKiogUmVjb3JkIG9mIHRoZSBtZWFzdXJtZW50cyBkZXRlcm1pbmluZyB3aGV0aGVyIGFuIG92ZXJsYXkgd2lsbCBmaXQgaW4gYSBzcGVjaWZpYyBwb3NpdGlvbi4gKi9cbmludGVyZmFjZSBGYWxsYmFja1Bvc2l0aW9uIHtcbiAgcG9zaXRpb246IENvbm5lY3RlZFBvc2l0aW9uO1xuICBvcmlnaW5Qb2ludDogUG9pbnQ7XG4gIG92ZXJsYXlQb2ludDogUG9pbnQ7XG4gIG92ZXJsYXlGaXQ6IE92ZXJsYXlGaXQ7XG4gIG92ZXJsYXlSZWN0OiBDbGllbnRSZWN0O1xufVxuXG4vKiogUG9zaXRpb24gYW5kIHNpemUgb2YgdGhlIG92ZXJsYXkgc2l6aW5nIHdyYXBwZXIgZm9yIGEgc3BlY2lmaWMgcG9zaXRpb24uICovXG5pbnRlcmZhY2UgQm91bmRpbmdCb3hSZWN0IHtcbiAgdG9wOiBudW1iZXI7XG4gIGxlZnQ6IG51bWJlcjtcbiAgYm90dG9tOiBudW1iZXI7XG4gIHJpZ2h0OiBudW1iZXI7XG4gIGhlaWdodDogbnVtYmVyO1xuICB3aWR0aDogbnVtYmVyO1xufVxuXG4vKiogUmVjb3JkIG9mIG1lYXN1cmVzIGRldGVybWluaW5nIGhvdyB3ZWxsIGEgZ2l2ZW4gcG9zaXRpb24gd2lsbCBmaXQgd2l0aCBmbGV4aWJsZSBkaW1lbnNpb25zLiAqL1xuaW50ZXJmYWNlIEZsZXhpYmxlRml0IHtcbiAgcG9zaXRpb246IENvbm5lY3RlZFBvc2l0aW9uO1xuICBvcmlnaW46IFBvaW50O1xuICBvdmVybGF5UmVjdDogQ2xpZW50UmVjdDtcbiAgYm91bmRpbmdCb3hSZWN0OiBCb3VuZGluZ0JveFJlY3Q7XG59XG5cbi8qKiBBIGNvbm5lY3RlZCBwb3NpdGlvbiBhcyBzcGVjaWZpZWQgYnkgdGhlIHVzZXIuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbm5lY3RlZFBvc2l0aW9uIHtcbiAgb3JpZ2luWDogJ3N0YXJ0JyB8ICdjZW50ZXInIHwgJ2VuZCc7XG4gIG9yaWdpblk6ICd0b3AnIHwgJ2NlbnRlcicgfCAnYm90dG9tJztcblxuICBvdmVybGF5WDogJ3N0YXJ0JyB8ICdjZW50ZXInIHwgJ2VuZCc7XG4gIG92ZXJsYXlZOiAndG9wJyB8ICdjZW50ZXInIHwgJ2JvdHRvbSc7XG5cbiAgd2VpZ2h0PzogbnVtYmVyO1xuICBvZmZzZXRYPzogbnVtYmVyO1xuICBvZmZzZXRZPzogbnVtYmVyO1xuICBwYW5lbENsYXNzPzogc3RyaW5nIHwgc3RyaW5nW107XG59XG5cbi8qKiBTaGFsbG93LWV4dGVuZHMgYSBzdHlsZXNoZWV0IG9iamVjdCB3aXRoIGFub3RoZXIgc3R5bGVzaGVldCBvYmplY3QuICovXG5mdW5jdGlvbiBleHRlbmRTdHlsZXMoZGVzdGluYXRpb246IENTU1N0eWxlRGVjbGFyYXRpb24sXG4gICAgICAgICAgICAgICAgICAgICAgc291cmNlOiBDU1NTdHlsZURlY2xhcmF0aW9uKTogQ1NTU3R5bGVEZWNsYXJhdGlvbiB7XG4gIGZvciAobGV0IGtleSBpbiBzb3VyY2UpIHtcbiAgICBpZiAoc291cmNlLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgIGRlc3RpbmF0aW9uW2tleV0gPSBzb3VyY2Vba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZGVzdGluYXRpb247XG59XG5cblxuLyoqXG4gKiBFeHRyYWN0cyB0aGUgcGl4ZWwgdmFsdWUgYXMgYSBudW1iZXIgZnJvbSBhIHZhbHVlLCBpZiBpdCdzIGEgbnVtYmVyXG4gKiBvciBhIENTUyBwaXhlbCBzdHJpbmcgKGUuZy4gYDEzMzdweGApLiBPdGhlcndpc2UgcmV0dXJucyBudWxsLlxuICovXG5mdW5jdGlvbiBnZXRQaXhlbFZhbHVlKGlucHV0OiBudW1iZXJ8c3RyaW5nfG51bGx8dW5kZWZpbmVkKTogbnVtYmVyfG51bGwge1xuICBpZiAodHlwZW9mIGlucHV0ICE9PSAnbnVtYmVyJyAmJiBpbnB1dCAhPSBudWxsKSB7XG4gICAgY29uc3QgW3ZhbHVlLCB1bml0c10gPSBpbnB1dC5zcGxpdChjc3NVbml0UGF0dGVybik7XG4gICAgcmV0dXJuICghdW5pdHMgfHwgdW5pdHMgPT09ICdweCcpID8gcGFyc2VGbG9hdCh2YWx1ZSkgOiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIGlucHV0IHx8IG51bGw7XG59XG5cbi8qKlxuICogR2V0cyBhIHZlcnNpb24gb2YgYW4gZWxlbWVudCdzIGJvdW5kaW5nIGBDbGllbnRSZWN0YCB3aGVyZSBhbGwgdGhlIHZhbHVlcyBhcmUgcm91bmRlZCBkb3duIHRvXG4gKiB0aGUgbmVhcmVzdCBwaXhlbC4gVGhpcyBhbGxvd3MgdXMgdG8gYWNjb3VudCBmb3IgdGhlIGNhc2VzIHdoZXJlIHRoZXJlIG1heSBiZSBzdWItcGl4ZWxcbiAqIGRldmlhdGlvbnMgaW4gdGhlIGBDbGllbnRSZWN0YCByZXR1cm5lZCBieSB0aGUgYnJvd3NlciAoZS5nLiB3aGVuIHpvb21lZCBpbiB3aXRoIGEgcGVyY2VudGFnZVxuICogc2l6ZSwgc2VlICMyMTM1MCkuXG4gKi9cbmZ1bmN0aW9uIGdldFJvdW5kZWRCb3VuZGluZ0NsaWVudFJlY3QoY2xpZW50UmVjdDogQ2xpZW50UmVjdCk6IENsaWVudFJlY3Qge1xuICByZXR1cm4ge1xuICAgIHRvcDogTWF0aC5mbG9vcihjbGllbnRSZWN0LnRvcCksXG4gICAgcmlnaHQ6IE1hdGguZmxvb3IoY2xpZW50UmVjdC5yaWdodCksXG4gICAgYm90dG9tOiBNYXRoLmZsb29yKGNsaWVudFJlY3QuYm90dG9tKSxcbiAgICBsZWZ0OiBNYXRoLmZsb29yKGNsaWVudFJlY3QubGVmdCksXG4gICAgd2lkdGg6IE1hdGguZmxvb3IoY2xpZW50UmVjdC53aWR0aCksXG4gICAgaGVpZ2h0OiBNYXRoLmZsb29yKGNsaWVudFJlY3QuaGVpZ2h0KVxuICB9O1xufVxuIl19
|