@spartan-ng/brain 0.0.1-alpha.373 → 0.0.1-alpha.379
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/accordion/README.md +3 -0
- package/accordion/index.d.ts +13 -0
- package/accordion/lib/brn-accordion-content.component.d.ts +15 -0
- package/accordion/lib/brn-accordion.directive.d.ts +47 -0
- package/alert-dialog/README.md +3 -0
- package/alert-dialog/index.d.ts +25 -0
- package/alert-dialog/lib/brn-alert-dialog-content.directive.d.ts +6 -0
- package/alert-dialog/lib/brn-alert-dialog-description.directive.d.ts +6 -0
- package/alert-dialog/lib/brn-alert-dialog-overlay.component.d.ts +6 -0
- package/alert-dialog/lib/brn-alert-dialog-title.directive.d.ts +6 -0
- package/alert-dialog/lib/brn-alert-dialog-trigger.directive.d.ts +8 -0
- package/alert-dialog/lib/brn-alert-dialog.component.d.ts +7 -0
- package/avatar/README.md +3 -0
- package/avatar/index.d.ts +17 -0
- package/avatar/lib/brn-avatar.component.d.ts +7 -0
- package/avatar/lib/fallback/brn-avatar-fallback.directive.d.ts +11 -0
- package/avatar/lib/fallback/index.d.ts +1 -0
- package/avatar/lib/image/brn-avatar-image.directive.d.ts +9 -0
- package/avatar/lib/image/index.d.ts +1 -0
- package/avatar/lib/util/hex-color-for.d.ts +1 -0
- package/avatar/lib/util/index.d.ts +3 -0
- package/avatar/lib/util/initials.pipe.d.ts +7 -0
- package/avatar/lib/util/is-bright.d.ts +1 -0
- package/calendar/README.md +3 -0
- package/calendar/index.d.ts +36 -0
- package/calendar/lib/brn-calendar-cell-button.directive.d.ts +59 -0
- package/calendar/lib/brn-calendar-cell.directive.d.ts +5 -0
- package/calendar/lib/brn-calendar-grid.directive.d.ts +7 -0
- package/calendar/lib/brn-calendar-header.directive.d.ts +7 -0
- package/calendar/lib/brn-calendar-next-button.directive.d.ts +13 -0
- package/calendar/lib/brn-calendar-previous-button.directive.d.ts +13 -0
- package/calendar/lib/brn-calendar-week.directive.d.ts +25 -0
- package/calendar/lib/brn-calendar-weekday.directive.d.ts +25 -0
- package/calendar/lib/brn-calendar.directive.d.ts +55 -0
- package/calendar/lib/brn-calendar.token.d.ts +8 -0
- package/calendar/lib/i18n/calendar-i18n.d.ts +17 -0
- package/checkbox/lib/brn-checkbox.component.d.ts +1 -1
- package/collapsible/README.md +3 -0
- package/collapsible/index.d.ts +16 -0
- package/collapsible/lib/brn-collapsible-content.component.d.ts +19 -0
- package/collapsible/lib/brn-collapsible-trigger.directive.d.ts +12 -0
- package/collapsible/lib/brn-collapsible.component.d.ts +11 -0
- package/command/README.md +3 -0
- package/command/index.d.ts +33 -0
- package/command/lib/brn-command-empty.directive.d.ts +6 -0
- package/command/lib/brn-command-group.component.d.ts +6 -0
- package/command/lib/brn-command-input.directive.d.ts +6 -0
- package/command/lib/brn-command-item.directive.d.ts +6 -0
- package/command/lib/brn-command-list.component.d.ts +6 -0
- package/command/lib/brn-command-loader.directive.d.ts +6 -0
- package/command/lib/brn-command-separator.component.d.ts +6 -0
- package/command/lib/brn-command.component.d.ts +6 -0
- package/date-time/README.md +3 -0
- package/date-time/index.d.ts +2 -0
- package/date-time/lib/date-adapter.d.ts +176 -0
- package/date-time/lib/native-date-adapter.d.ts +103 -0
- package/date-time-luxon/README.md +3 -0
- package/date-time-luxon/index.d.ts +1 -0
- package/date-time-luxon/lib/date-adapter.d.ts +29 -0
- package/dialog/README.md +3 -0
- package/dialog/index.d.ts +33 -0
- package/dialog/lib/brn-dialog-close.directive.d.ts +10 -0
- package/dialog/lib/brn-dialog-content.directive.d.ts +12 -0
- package/dialog/lib/brn-dialog-description.directive.d.ts +8 -0
- package/dialog/lib/brn-dialog-options.d.ts +26 -0
- package/dialog/lib/brn-dialog-overlay.component.d.ts +8 -0
- package/dialog/lib/brn-dialog-ref.d.ts +24 -0
- package/dialog/lib/brn-dialog-state.d.ts +1 -0
- package/dialog/lib/brn-dialog-title.directive.d.ts +8 -0
- package/dialog/lib/brn-dialog-trigger.directive.d.ts +16 -0
- package/dialog/lib/brn-dialog-utils.d.ts +1 -0
- package/dialog/lib/brn-dialog.component.d.ts +56 -0
- package/dialog/lib/brn-dialog.service.d.ts +22 -0
- package/esm2022/accordion/index.mjs +31 -0
- package/esm2022/accordion/lib/brn-accordion-content.component.mjs +50 -0
- package/esm2022/accordion/lib/brn-accordion.directive.mjs +180 -0
- package/esm2022/accordion/spartan-ng-brain-accordion.mjs +5 -0
- package/esm2022/alert-dialog/index.mjs +45 -0
- package/esm2022/alert-dialog/lib/brn-alert-dialog-content.directive.mjs +17 -0
- package/esm2022/alert-dialog/lib/brn-alert-dialog-description.directive.mjs +18 -0
- package/esm2022/alert-dialog/lib/brn-alert-dialog-overlay.component.mjs +20 -0
- package/esm2022/alert-dialog/lib/brn-alert-dialog-title.directive.mjs +18 -0
- package/esm2022/alert-dialog/lib/brn-alert-dialog-trigger.directive.mjs +27 -0
- package/esm2022/alert-dialog/lib/brn-alert-dialog.component.mjs +40 -0
- package/esm2022/alert-dialog/spartan-ng-brain-alert-dialog.mjs +5 -0
- package/esm2022/avatar/index.mjs +23 -0
- package/esm2022/avatar/lib/brn-avatar.component.mjs +31 -0
- package/esm2022/avatar/lib/fallback/brn-avatar-fallback.directive.mjs +21 -0
- package/esm2022/avatar/lib/fallback/index.mjs +2 -0
- package/esm2022/avatar/lib/image/brn-avatar-image.directive.mjs +29 -0
- package/esm2022/avatar/lib/image/index.mjs +2 -0
- package/esm2022/avatar/lib/util/hex-color-for.mjs +22 -0
- package/esm2022/avatar/lib/util/index.mjs +4 -0
- package/esm2022/avatar/lib/util/initials.pipe.mjs +27 -0
- package/esm2022/avatar/lib/util/is-bright.mjs +12 -0
- package/esm2022/avatar/spartan-ng-brain-avatar.mjs +5 -0
- package/esm2022/calendar/index.mjs +62 -0
- package/esm2022/calendar/lib/brn-calendar-cell-button.directive.mjs +160 -0
- package/esm2022/calendar/lib/brn-calendar-cell.directive.mjs +17 -0
- package/esm2022/calendar/lib/brn-calendar-grid.directive.mjs +21 -0
- package/esm2022/calendar/lib/brn-calendar-header.directive.mjs +22 -0
- package/esm2022/calendar/lib/brn-calendar-next-button.directive.mjs +42 -0
- package/esm2022/calendar/lib/brn-calendar-previous-button.directive.mjs +42 -0
- package/esm2022/calendar/lib/brn-calendar-week.directive.mjs +64 -0
- package/esm2022/calendar/lib/brn-calendar-weekday.directive.mjs +48 -0
- package/esm2022/calendar/lib/brn-calendar.directive.mjs +154 -0
- package/esm2022/calendar/lib/brn-calendar.token.mjs +12 -0
- package/esm2022/calendar/lib/i18n/calendar-i18n.mjs +33 -0
- package/esm2022/calendar/spartan-ng-brain-calendar.mjs +5 -0
- package/esm2022/checkbox/lib/brn-checkbox.component.mjs +1 -1
- package/esm2022/collapsible/index.mjs +30 -0
- package/esm2022/collapsible/lib/brn-collapsible-content.component.mjs +61 -0
- package/esm2022/collapsible/lib/brn-collapsible-trigger.directive.mjs +35 -0
- package/esm2022/collapsible/lib/brn-collapsible.component.mjs +33 -0
- package/esm2022/collapsible/spartan-ng-brain-collapsible.mjs +5 -0
- package/esm2022/command/index.mjs +64 -0
- package/esm2022/command/lib/brn-command-empty.directive.mjs +29 -0
- package/esm2022/command/lib/brn-command-group.component.mjs +45 -0
- package/esm2022/command/lib/brn-command-input.directive.mjs +29 -0
- package/esm2022/command/lib/brn-command-item.directive.mjs +36 -0
- package/esm2022/command/lib/brn-command-list.component.mjs +35 -0
- package/esm2022/command/lib/brn-command-loader.directive.mjs +29 -0
- package/esm2022/command/lib/brn-command-separator.component.mjs +30 -0
- package/esm2022/command/lib/brn-command.component.mjs +21 -0
- package/esm2022/command/spartan-ng-brain-command.mjs +5 -0
- package/esm2022/date-time/index.mjs +3 -0
- package/esm2022/date-time/lib/date-adapter.mjs +16 -0
- package/esm2022/date-time/lib/native-date-adapter.mjs +155 -0
- package/esm2022/date-time/spartan-ng-brain-date-time.mjs +5 -0
- package/esm2022/date-time-luxon/index.mjs +2 -0
- package/esm2022/date-time-luxon/lib/date-adapter.mjs +85 -0
- package/esm2022/date-time-luxon/spartan-ng-brain-date-time-luxon.mjs +5 -0
- package/esm2022/dialog/index.mjs +55 -0
- package/esm2022/dialog/lib/brn-dialog-close.directive.mjs +29 -0
- package/esm2022/dialog/lib/brn-dialog-content.directive.mjs +41 -0
- package/esm2022/dialog/lib/brn-dialog-description.directive.mjs +25 -0
- package/esm2022/dialog/lib/brn-dialog-options.mjs +19 -0
- package/esm2022/dialog/lib/brn-dialog-overlay.component.mjs +29 -0
- package/esm2022/dialog/lib/brn-dialog-ref.mjs +53 -0
- package/esm2022/dialog/lib/brn-dialog-state.mjs +2 -0
- package/esm2022/dialog/lib/brn-dialog-title.directive.mjs +25 -0
- package/esm2022/dialog/lib/brn-dialog-trigger.directive.mjs +39 -0
- package/esm2022/dialog/lib/brn-dialog-utils.mjs +12 -0
- package/esm2022/dialog/lib/brn-dialog.component.mjs +208 -0
- package/esm2022/dialog/lib/brn-dialog.service.mjs +127 -0
- package/esm2022/dialog/spartan-ng-brain-dialog.mjs +5 -0
- package/esm2022/form-field/index.mjs +2 -0
- package/esm2022/form-field/lib/brn-form-field-control.mjs +14 -0
- package/esm2022/form-field/spartan-ng-brain-form-field.mjs +5 -0
- package/esm2022/forms/index.mjs +4 -0
- package/esm2022/forms/lib/control-value-accessor.mjs +2 -0
- package/esm2022/forms/lib/error-options.mjs +26 -0
- package/esm2022/forms/lib/error-state-tracker.mjs +29 -0
- package/esm2022/forms/spartan-ng-brain-forms.mjs +5 -0
- package/esm2022/hover-card/index.mjs +29 -0
- package/esm2022/hover-card/lib/brn-hover-card-content.service.mjs +205 -0
- package/esm2022/hover-card/lib/brn-hover-card.component.mjs +34 -0
- package/esm2022/hover-card/lib/createHoverObservable.mjs +19 -0
- package/esm2022/hover-card/spartan-ng-brain-hover-card.mjs +5 -0
- package/esm2022/label/index.mjs +17 -0
- package/esm2022/label/lib/brn-label.directive.mjs +49 -0
- package/esm2022/label/spartan-ng-brain-label.mjs +5 -0
- package/esm2022/menu/index.mjs +100 -0
- package/esm2022/menu/lib/brn-context-menu-trigger.directive.mjs +40 -0
- package/esm2022/menu/lib/brn-menu-align.mjs +15 -0
- package/esm2022/menu/lib/brn-menu-bar.directive.mjs +17 -0
- package/esm2022/menu/lib/brn-menu-group.directive.mjs +17 -0
- package/esm2022/menu/lib/brn-menu-item-checkbox.directive.mjs +30 -0
- package/esm2022/menu/lib/brn-menu-item-radio.directive.mjs +30 -0
- package/esm2022/menu/lib/brn-menu-item.directive.mjs +27 -0
- package/esm2022/menu/lib/brn-menu-trigger.directive.mjs +36 -0
- package/esm2022/menu/lib/brn-menu.directive.mjs +50 -0
- package/esm2022/menu/spartan-ng-brain-menu.mjs +5 -0
- package/esm2022/popover/index.mjs +35 -0
- package/esm2022/popover/lib/brn-popover-close.directive.mjs +15 -0
- package/esm2022/popover/lib/brn-popover-content.directive.mjs +17 -0
- package/esm2022/popover/lib/brn-popover-trigger.directive.mjs +37 -0
- package/esm2022/popover/lib/brn-popover.component.mjs +81 -0
- package/esm2022/popover/spartan-ng-brain-popover.mjs +5 -0
- package/esm2022/progress/index.mjs +21 -0
- package/esm2022/progress/lib/brn-progress-indicator.component.mjs +22 -0
- package/esm2022/progress/lib/brn-progress.component.mjs +61 -0
- package/esm2022/progress/lib/brn-progress.token.mjs +9 -0
- package/esm2022/progress/spartan-ng-brain-progress.mjs +5 -0
- package/esm2022/radio-group/index.mjs +20 -0
- package/esm2022/radio-group/lib/brn-radio-group.component.mjs +90 -0
- package/esm2022/radio-group/lib/brn-radio-group.token.mjs +9 -0
- package/esm2022/radio-group/lib/brn-radio.component.mjs +185 -0
- package/esm2022/radio-group/spartan-ng-brain-radio-group.mjs +5 -0
- package/esm2022/select/index.mjs +56 -0
- package/esm2022/select/lib/brn-select-content.component.mjs +204 -0
- package/esm2022/select/lib/brn-select-group.directive.mjs +19 -0
- package/esm2022/select/lib/brn-select-label.directive.mjs +23 -0
- package/esm2022/select/lib/brn-select-option.directive.mjs +65 -0
- package/esm2022/select/lib/brn-select-value.component.mjs +46 -0
- package/esm2022/select/lib/brn-select.component.mjs +358 -0
- package/esm2022/select/lib/brn-select.service.mjs +197 -0
- package/esm2022/select/spartan-ng-brain-select.mjs +5 -0
- package/esm2022/separator/index.mjs +17 -0
- package/esm2022/separator/lib/brn-separator.component.mjs +24 -0
- package/esm2022/separator/spartan-ng-brain-separator.mjs +5 -0
- package/esm2022/sheet/index.mjs +50 -0
- package/esm2022/sheet/lib/brn-sheet-close.directive.mjs +15 -0
- package/esm2022/sheet/lib/brn-sheet-content.directive.mjs +25 -0
- package/esm2022/sheet/lib/brn-sheet-description.directive.mjs +18 -0
- package/esm2022/sheet/lib/brn-sheet-overlay.component.mjs +20 -0
- package/esm2022/sheet/lib/brn-sheet-title.directive.mjs +18 -0
- package/esm2022/sheet/lib/brn-sheet-trigger.directive.mjs +26 -0
- package/esm2022/sheet/lib/brn-sheet.component.mjs +55 -0
- package/esm2022/sheet/spartan-ng-brain-sheet.mjs +5 -0
- package/esm2022/slider/index.mjs +13 -0
- package/esm2022/slider/lib/brn-slider-thumb.directive.mjs +41 -0
- package/esm2022/slider/lib/brn-slider-tick-mark.directive.mjs +37 -0
- package/esm2022/slider/lib/brn-slider-track-active-fill.directive.mjs +29 -0
- package/esm2022/slider/lib/brn-slider-track.directive.mjs +290 -0
- package/esm2022/slider/spartan-ng-brain-slider.mjs +5 -0
- package/esm2022/switch/index.mjs +20 -0
- package/esm2022/switch/lib/brn-switch-thumb.component.mjs +16 -0
- package/esm2022/switch/lib/brn-switch.component.mjs +236 -0
- package/esm2022/switch/spartan-ng-brain-switch.mjs +5 -0
- package/esm2022/table/index.mjs +47 -0
- package/esm2022/table/lib/brn-cell-def.directive.mjs +22 -0
- package/esm2022/table/lib/brn-column-def.component.mjs +82 -0
- package/esm2022/table/lib/brn-column-manager.mjs +61 -0
- package/esm2022/table/lib/brn-footer-def.directive.mjs +22 -0
- package/esm2022/table/lib/brn-header-def.directive.mjs +22 -0
- package/esm2022/table/lib/brn-paginator.directive.mjs +109 -0
- package/esm2022/table/lib/brn-table.component.mjs +169 -0
- package/esm2022/table/spartan-ng-brain-table.mjs +5 -0
- package/esm2022/tabs/index.mjs +32 -0
- package/esm2022/tabs/lib/brn-tabs-list.directive.mjs +65 -0
- package/esm2022/tabs/lib/brn-tabs-paginated-list.directive.mjs +525 -0
- package/esm2022/tabs/lib/brn-tabs-trigger.directive.mjs +134 -0
- package/esm2022/tabs/spartan-ng-brain-tabs.mjs +5 -0
- package/esm2022/toggle/index.mjs +31 -0
- package/esm2022/toggle/lib/brn-toggle-group.component.mjs +159 -0
- package/esm2022/toggle/lib/brn-toggle-group.token.mjs +9 -0
- package/esm2022/toggle/lib/brn-toggle.directive.mjs +65 -0
- package/esm2022/toggle/spartan-ng-brain-toggle.mjs +5 -0
- package/esm2022/tooltip/index.mjs +35 -0
- package/esm2022/tooltip/lib/brn-tooltip-content.component.mjs +228 -0
- package/esm2022/tooltip/lib/brn-tooltip-content.directive.mjs +22 -0
- package/esm2022/tooltip/lib/brn-tooltip-trigger.directive.mjs +689 -0
- package/esm2022/tooltip/lib/brn-tooltip.directive.mjs +15 -0
- package/esm2022/tooltip/spartan-ng-brain-tooltip.mjs +5 -0
- package/fesm2022/spartan-ng-brain-accordion.mjs +259 -0
- package/fesm2022/spartan-ng-brain-accordion.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-alert-dialog.mjs +162 -0
- package/fesm2022/spartan-ng-brain-alert-dialog.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-avatar.mjs +156 -0
- package/fesm2022/spartan-ng-brain-avatar.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-calendar.mjs +629 -0
- package/fesm2022/spartan-ng-brain-calendar.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-checkbox.mjs.map +1 -1
- package/fesm2022/spartan-ng-brain-collapsible.mjs +152 -0
- package/fesm2022/spartan-ng-brain-collapsible.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-command.mjs +284 -0
- package/fesm2022/spartan-ng-brain-command.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-date-time-luxon.mjs +92 -0
- package/fesm2022/spartan-ng-brain-date-time-luxon.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-date-time.mjs +177 -0
- package/fesm2022/spartan-ng-brain-date-time.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-dialog.mjs +617 -0
- package/fesm2022/spartan-ng-brain-dialog.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-form-field.mjs +21 -0
- package/fesm2022/spartan-ng-brain-form-field.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-forms.mjs +61 -0
- package/fesm2022/spartan-ng-brain-forms.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-hover-card.mjs +274 -0
- package/fesm2022/spartan-ng-brain-hover-card.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-label.mjs +69 -0
- package/fesm2022/spartan-ng-brain-label.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-menu.mjs +316 -0
- package/fesm2022/spartan-ng-brain-menu.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-popover.mjs +173 -0
- package/fesm2022/spartan-ng-brain-popover.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-progress.mjs +108 -0
- package/fesm2022/spartan-ng-brain-progress.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-radio-group.mjs +299 -0
- package/fesm2022/spartan-ng-brain-radio-group.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-select.mjs +928 -0
- package/fesm2022/spartan-ng-brain-select.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-separator.mjs +44 -0
- package/fesm2022/spartan-ng-brain-separator.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-sheet.mjs +197 -0
- package/fesm2022/spartan-ng-brain-sheet.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-slider.mjs +399 -0
- package/fesm2022/spartan-ng-brain-slider.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-switch.mjs +271 -0
- package/fesm2022/spartan-ng-brain-switch.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-table.mjs +506 -0
- package/fesm2022/spartan-ng-brain-table.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-tabs.mjs +748 -0
- package/fesm2022/spartan-ng-brain-tabs.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-toggle.mjs +260 -0
- package/fesm2022/spartan-ng-brain-toggle.mjs.map +1 -0
- package/fesm2022/spartan-ng-brain-tooltip.mjs +975 -0
- package/fesm2022/spartan-ng-brain-tooltip.mjs.map +1 -0
- package/form-field/README.md +3 -0
- package/form-field/index.d.ts +1 -0
- package/form-field/lib/brn-form-field-control.d.ts +11 -0
- package/forms/README.md +3 -0
- package/forms/index.d.ts +3 -0
- package/forms/lib/control-value-accessor.d.ts +2 -0
- package/forms/lib/error-options.d.ts +14 -0
- package/forms/lib/error-state-tracker.d.ts +15 -0
- package/hover-card/README.md +3 -0
- package/hover-card/index.d.ts +14 -0
- package/hover-card/lib/brn-hover-card-content.service.d.ts +65 -0
- package/hover-card/lib/brn-hover-card.component.d.ts +9 -0
- package/hover-card/lib/createHoverObservable.d.ts +4 -0
- package/label/README.md +3 -0
- package/label/index.d.ts +8 -0
- package/label/lib/brn-label.directive.d.ts +15 -0
- package/menu/README.md +3 -0
- package/menu/index.d.ts +49 -0
- package/menu/lib/brn-context-menu-trigger.directive.d.ts +13 -0
- package/menu/lib/brn-menu-align.d.ts +3 -0
- package/menu/lib/brn-menu-bar.directive.d.ts +6 -0
- package/menu/lib/brn-menu-group.directive.d.ts +6 -0
- package/menu/lib/brn-menu-item-checkbox.directive.d.ts +11 -0
- package/menu/lib/brn-menu-item-radio.directive.d.ts +11 -0
- package/menu/lib/brn-menu-item.directive.d.ts +10 -0
- package/menu/lib/brn-menu-trigger.directive.d.ts +10 -0
- package/menu/lib/brn-menu.directive.d.ts +11 -0
- package/package.json +182 -9
- package/popover/README.md +3 -0
- package/popover/index.d.ts +19 -0
- package/popover/lib/brn-popover-close.directive.d.ts +6 -0
- package/popover/lib/brn-popover-content.directive.d.ts +6 -0
- package/popover/lib/brn-popover-trigger.directive.d.ts +10 -0
- package/popover/lib/brn-popover.component.d.ts +14 -0
- package/progress/README.md +3 -0
- package/progress/index.d.ts +14 -0
- package/progress/lib/brn-progress-indicator.component.d.ts +6 -0
- package/progress/lib/brn-progress.component.d.ts +15 -0
- package/progress/lib/brn-progress.token.d.ts +4 -0
- package/radio-group/README.md +3 -0
- package/radio-group/index.d.ts +13 -0
- package/radio-group/lib/brn-radio-group.component.d.ts +57 -0
- package/radio-group/lib/brn-radio-group.token.d.ts +4 -0
- package/radio-group/lib/brn-radio.component.d.ts +58 -0
- package/select/README.md +3 -0
- package/select/index.d.ts +28 -0
- package/select/lib/brn-select-content.component.d.ts +50 -0
- package/select/lib/brn-select-group.directive.d.ts +6 -0
- package/select/lib/brn-select-label.directive.d.ts +9 -0
- package/select/lib/brn-select-option.directive.d.ts +25 -0
- package/select/lib/brn-select-value.component.d.ts +11 -0
- package/select/lib/brn-select.component.d.ts +82 -0
- package/select/lib/brn-select.service.d.ts +67 -0
- package/separator/README.md +3 -0
- package/separator/index.d.ts +8 -0
- package/separator/lib/brn-separator.component.d.ts +11 -0
- package/sheet/README.md +3 -0
- package/sheet/index.d.ts +28 -0
- package/sheet/lib/brn-sheet-close.directive.d.ts +6 -0
- package/sheet/lib/brn-sheet-content.directive.d.ts +8 -0
- package/sheet/lib/brn-sheet-description.directive.d.ts +6 -0
- package/sheet/lib/brn-sheet-overlay.component.d.ts +6 -0
- package/sheet/lib/brn-sheet-title.directive.d.ts +6 -0
- package/sheet/lib/brn-sheet-trigger.directive.d.ts +9 -0
- package/sheet/lib/brn-sheet.component.d.ts +9 -0
- package/slider/README.md +3 -0
- package/slider/index.d.ts +7 -0
- package/slider/lib/brn-slider-thumb.directive.d.ts +17 -0
- package/slider/lib/brn-slider-tick-mark.directive.d.ts +15 -0
- package/slider/lib/brn-slider-track-active-fill.directive.d.ts +10 -0
- package/slider/lib/brn-slider-track.directive.d.ts +139 -0
- package/switch/README.md +3 -0
- package/switch/index.d.ts +13 -0
- package/switch/lib/brn-switch-thumb.component.d.ts +5 -0
- package/switch/lib/brn-switch.component.d.ts +58 -0
- package/table/README.md +3 -0
- package/table/index.d.ts +26 -0
- package/table/lib/brn-cell-def.directive.d.ts +9 -0
- package/table/lib/brn-column-def.component.d.ts +18 -0
- package/table/lib/brn-column-manager.d.ts +26 -0
- package/table/lib/brn-footer-def.directive.d.ts +9 -0
- package/table/lib/brn-header-def.directive.d.ts +9 -0
- package/table/lib/brn-paginator.directive.d.ts +41 -0
- package/table/lib/brn-table.component.d.ts +37 -0
- package/tabs/README.md +3 -0
- package/tabs/index.d.ts +14 -0
- package/tabs/lib/brn-tabs-list.directive.d.ts +17 -0
- package/tabs/lib/brn-tabs-paginated-list.directive.d.ts +196 -0
- package/tabs/lib/brn-tabs-trigger.directive.d.ts +61 -0
- package/toggle/README.md +3 -0
- package/toggle/index.d.ts +15 -0
- package/toggle/lib/brn-toggle-group.component.d.ts +68 -0
- package/toggle/lib/brn-toggle-group.token.d.ts +4 -0
- package/toggle/lib/brn-toggle.directive.d.ts +25 -0
- package/tooltip/README.md +3 -0
- package/tooltip/index.d.ts +19 -0
- package/tooltip/lib/brn-tooltip-content.component.d.ts +73 -0
- package/tooltip/lib/brn-tooltip-content.directive.d.ts +8 -0
- package/tooltip/lib/brn-tooltip-trigger.directive.d.ts +177 -0
- package/tooltip/lib/brn-tooltip.directive.d.ts +7 -0
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* We are building on shoulders of giants here and adapt the implementation provided by the incredible Angular
|
|
3
|
+
* team: https://github.com/angular/components/blob/main/src/material/tabs/paginated-tab-header.ts
|
|
4
|
+
* Check them out! Give them a try! Leave a star! Their work is incredible!
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* @license
|
|
8
|
+
* Copyright Google LLC All Rights Reserved.
|
|
9
|
+
*
|
|
10
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
11
|
+
* found in the LICENSE file at https://angular.io/license
|
|
12
|
+
*/
|
|
13
|
+
import { FocusKeyManager } from '@angular/cdk/a11y';
|
|
14
|
+
import { Directionality } from '@angular/cdk/bidi';
|
|
15
|
+
import { ENTER, SPACE, hasModifierKey } from '@angular/cdk/keycodes';
|
|
16
|
+
import { SharedResizeObserver } from '@angular/cdk/observers/private';
|
|
17
|
+
import { Platform, normalizePassiveListenerOptions } from '@angular/cdk/platform';
|
|
18
|
+
import { ViewportRuler } from '@angular/cdk/scrolling';
|
|
19
|
+
import { ANIMATION_MODULE_TYPE, ChangeDetectorRef, Directive, ElementRef, Injector, NgZone, afterNextRender, booleanAttribute, computed, effect, inject, input, output, signal, } from '@angular/core';
|
|
20
|
+
import { EMPTY, Observable, Subject, fromEvent, merge, of as observableOf, timer } from 'rxjs';
|
|
21
|
+
import { debounceTime, filter, skip, startWith, switchMap, takeUntil } from 'rxjs/operators';
|
|
22
|
+
import { BrnTabsDirective } from './brn-tabs-trigger.directive';
|
|
23
|
+
import * as i0 from "@angular/core";
|
|
24
|
+
/** Config used to bind passive event listeners */
|
|
25
|
+
const passiveEventListenerOptions = normalizePassiveListenerOptions({
|
|
26
|
+
passive: true,
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* Amount of milliseconds to wait before starting to scroll the header automatically.
|
|
30
|
+
* Set a little conservatively in order to handle fake events dispatched on touch devices.
|
|
31
|
+
*/
|
|
32
|
+
const HEADER_SCROLL_DELAY = 650;
|
|
33
|
+
/**
|
|
34
|
+
* Interval in milliseconds at which to scroll the header
|
|
35
|
+
* while the user is holding their pointer.
|
|
36
|
+
*/
|
|
37
|
+
const HEADER_SCROLL_INTERVAL = 100;
|
|
38
|
+
/**
|
|
39
|
+
* Base class for a tab header that supported pagination.
|
|
40
|
+
* @docs-private
|
|
41
|
+
*/
|
|
42
|
+
export class BrnTabsPaginatedListDirective {
|
|
43
|
+
/** The distance in pixels that the tab labels should be translated to the left. */
|
|
44
|
+
_scrollDistance = 0;
|
|
45
|
+
/** Whether the header should scroll to the selected index after the view has been checked. */
|
|
46
|
+
_selectedIndexChanged = false;
|
|
47
|
+
_root = inject(BrnTabsDirective);
|
|
48
|
+
_activeTab = this._root.$activeTab;
|
|
49
|
+
_tabs = this._root.$tabs;
|
|
50
|
+
/** Emits when the component is destroyed. */
|
|
51
|
+
_destroyed = new Subject();
|
|
52
|
+
/** Whether the controls for pagination should be displayed */
|
|
53
|
+
_showPaginationControls = signal(false);
|
|
54
|
+
/** Whether the tab list can be scrolled more towards the end of the tab label list. */
|
|
55
|
+
_disableScrollAfter = true;
|
|
56
|
+
/** Whether the tab list can be scrolled more towards the beginning of the tab label list. */
|
|
57
|
+
_disableScrollBefore = true;
|
|
58
|
+
/**
|
|
59
|
+
* The number of tab labels that are displayed on the header. When this changes, the header
|
|
60
|
+
* should re-evaluate the scroll position.
|
|
61
|
+
*/
|
|
62
|
+
_tabLabelCount;
|
|
63
|
+
/** Whether the scroll distance has changed and should be applied after the view is checked. */
|
|
64
|
+
_scrollDistanceChanged;
|
|
65
|
+
/** Used to manage focus between the tabs. */
|
|
66
|
+
_keyManager;
|
|
67
|
+
/** Cached text content of the header. */
|
|
68
|
+
_currentTextContent;
|
|
69
|
+
/** Stream that will stop the automated scrolling. */
|
|
70
|
+
_stopScrolling = new Subject();
|
|
71
|
+
/**
|
|
72
|
+
* Whether pagination should be disabled. This can be used to avoid unnecessary
|
|
73
|
+
* layout recalculations if it's known that pagination won't be required.
|
|
74
|
+
*/
|
|
75
|
+
disablePagination = input(false, { transform: booleanAttribute });
|
|
76
|
+
/** The index of the active tab. */
|
|
77
|
+
_selectedIndex = computed(() => {
|
|
78
|
+
const currentTabKey = this._activeTab();
|
|
79
|
+
const tabs = this._tabs();
|
|
80
|
+
let activeIndex = 0;
|
|
81
|
+
if (currentTabKey && this._items()) {
|
|
82
|
+
const currentTab = tabs[currentTabKey];
|
|
83
|
+
if (currentTab) {
|
|
84
|
+
activeIndex = this._items().indexOf(currentTab.trigger);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return activeIndex;
|
|
88
|
+
});
|
|
89
|
+
/** Event emitted when the option is selected. */
|
|
90
|
+
selectFocusedIndex = output();
|
|
91
|
+
/** Event emitted when a label is focused. */
|
|
92
|
+
indexFocused = output();
|
|
93
|
+
_sharedResizeObserver = inject(SharedResizeObserver);
|
|
94
|
+
_injector = inject(Injector);
|
|
95
|
+
_elementRef = inject(ElementRef);
|
|
96
|
+
_changeDetectorRef = inject(ChangeDetectorRef);
|
|
97
|
+
_viewportRuler = inject(ViewportRuler);
|
|
98
|
+
_dir = inject(Directionality, { optional: true });
|
|
99
|
+
_ngZone = inject(NgZone);
|
|
100
|
+
_platform = inject(Platform);
|
|
101
|
+
_animationMode = inject(ANIMATION_MODULE_TYPE, { optional: true });
|
|
102
|
+
constructor() {
|
|
103
|
+
// Bind the `mouseleave` event on the outside since it doesn't change anything in the view.
|
|
104
|
+
this._ngZone.runOutsideAngular(() => {
|
|
105
|
+
fromEvent(this._elementRef.nativeElement, 'mouseleave')
|
|
106
|
+
.pipe(takeUntil(this._destroyed))
|
|
107
|
+
.subscribe(() => {
|
|
108
|
+
this._stopInterval();
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
effect(() => {
|
|
112
|
+
const selectedIndex = this._selectedIndex();
|
|
113
|
+
if (selectedIndex !== 0) {
|
|
114
|
+
this._selectedIndexChanged = true;
|
|
115
|
+
if (this._keyManager) {
|
|
116
|
+
this._keyManager.updateActiveItem(selectedIndex);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
ngAfterViewInit() {
|
|
122
|
+
// We need to handle these events manually, because we want to bind passive event listeners.
|
|
123
|
+
fromEvent(this._previousPaginator().nativeElement, 'touchstart', passiveEventListenerOptions)
|
|
124
|
+
.pipe(takeUntil(this._destroyed))
|
|
125
|
+
.subscribe(() => {
|
|
126
|
+
this._handlePaginatorPress('before');
|
|
127
|
+
});
|
|
128
|
+
fromEvent(this._nextPaginator().nativeElement, 'touchstart', passiveEventListenerOptions)
|
|
129
|
+
.pipe(takeUntil(this._destroyed))
|
|
130
|
+
.subscribe(() => {
|
|
131
|
+
this._handlePaginatorPress('after');
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
ngAfterContentInit() {
|
|
135
|
+
const dirChange = this._dir ? this._dir.change : observableOf('ltr');
|
|
136
|
+
// We need to debounce resize events because the alignment logic is expensive.
|
|
137
|
+
// If someone animates the width of tabs, we don't want to realign on every animation frame.
|
|
138
|
+
// Once we haven't seen any more resize events in the last 32ms (~2 animaion frames) we can
|
|
139
|
+
// re-align.
|
|
140
|
+
const resize = this._sharedResizeObserver
|
|
141
|
+
.observe(this._elementRef.nativeElement)
|
|
142
|
+
.pipe(debounceTime(32), takeUntil(this._destroyed));
|
|
143
|
+
// Note: We do not actually need to watch these events for proper functioning of the tabs,
|
|
144
|
+
// the resize events above should capture any viewport resize that we care about. However,
|
|
145
|
+
// removing this is fairly breaking for screenshot tests, so we're leaving it here for now.
|
|
146
|
+
const viewportResize = this._viewportRuler.change(150).pipe(takeUntil(this._destroyed));
|
|
147
|
+
const realign = () => {
|
|
148
|
+
this.updatePagination();
|
|
149
|
+
};
|
|
150
|
+
this._keyManager = new FocusKeyManager(this._items())
|
|
151
|
+
.withHorizontalOrientation(this._getLayoutDirection())
|
|
152
|
+
.withHomeAndEnd()
|
|
153
|
+
.withWrap()
|
|
154
|
+
// Allow focus to land on disabled tabs, as per https://w3c.github.io/aria-practices/#kbd_disabled_controls
|
|
155
|
+
.skipPredicate(() => false);
|
|
156
|
+
this._keyManager.updateActiveItem(this._selectedIndex());
|
|
157
|
+
// Note: We do not need to realign after the first render for proper functioning of the tabs
|
|
158
|
+
// the resize events above should fire when we first start observing the element. However,
|
|
159
|
+
// removing this is fairly breaking for screenshot tests, so we're leaving it here for now.
|
|
160
|
+
afterNextRender(realign, { injector: this._injector });
|
|
161
|
+
// On dir change or resize, realign the ink bar and update the orientation of
|
|
162
|
+
// the key manager if the direction has changed.
|
|
163
|
+
merge(dirChange, viewportResize, resize, this._itemsChanges, this._itemsResized())
|
|
164
|
+
.pipe(takeUntil(this._destroyed))
|
|
165
|
+
.subscribe(() => {
|
|
166
|
+
// We need to defer this to give the browser some time to recalculate
|
|
167
|
+
// the element dimensions. The call has to be wrapped in `NgZone.run`,
|
|
168
|
+
// because the viewport change handler runs outside of Angular.
|
|
169
|
+
this._ngZone.run(() => {
|
|
170
|
+
Promise.resolve().then(() => {
|
|
171
|
+
// Clamp the scroll distance, because it can change with the number of tabs.
|
|
172
|
+
this._scrollDistance = Math.max(0, Math.min(this._getMaxScrollDistance(), this._scrollDistance));
|
|
173
|
+
realign();
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
this._keyManager.withHorizontalOrientation(this._getLayoutDirection());
|
|
177
|
+
});
|
|
178
|
+
// If there is a change in the focus key manager we need to emit the `indexFocused`
|
|
179
|
+
// event in order to provide a public event that notifies about focus changes. Also we realign
|
|
180
|
+
// the tabs container by scrolling the new focused tab into the visible section.
|
|
181
|
+
this._keyManager.change.subscribe((newFocusIndex) => {
|
|
182
|
+
this.indexFocused.emit(newFocusIndex);
|
|
183
|
+
this._setTabFocus(newFocusIndex);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
/** Sends any changes that could affect the layout of the items. */
|
|
187
|
+
_itemsResized() {
|
|
188
|
+
if (typeof ResizeObserver !== 'function') {
|
|
189
|
+
return EMPTY;
|
|
190
|
+
}
|
|
191
|
+
return this._itemsChanges.pipe(startWith(this._items()), switchMap((tabItems) => new Observable((observer) => this._ngZone.runOutsideAngular(() => {
|
|
192
|
+
const resizeObserver = new ResizeObserver((entries) => observer.next(entries));
|
|
193
|
+
for (const tabItem of tabItems) {
|
|
194
|
+
resizeObserver.observe(tabItem.elementRef.nativeElement);
|
|
195
|
+
}
|
|
196
|
+
return () => {
|
|
197
|
+
resizeObserver.disconnect();
|
|
198
|
+
};
|
|
199
|
+
}))),
|
|
200
|
+
// Skip the first emit since the resize observer emits when an item
|
|
201
|
+
// is observed for new items when the tab is already inserted
|
|
202
|
+
skip(1),
|
|
203
|
+
// Skip emissions where all the elements are invisible since we don't want
|
|
204
|
+
// the header to try and re-render with invalid measurements. See #25574.
|
|
205
|
+
filter((entries) => entries.some((e) => e.contentRect.width > 0 && e.contentRect.height > 0)));
|
|
206
|
+
}
|
|
207
|
+
ngAfterContentChecked() {
|
|
208
|
+
// If the number of tab labels have changed, check if scrolling should be enabled
|
|
209
|
+
if (this._tabLabelCount !== this._items().length) {
|
|
210
|
+
this.updatePagination();
|
|
211
|
+
this._tabLabelCount = this._items().length;
|
|
212
|
+
this._changeDetectorRef.markForCheck();
|
|
213
|
+
}
|
|
214
|
+
// If the selected index has changed, scroll to the label and check if the scrolling controls
|
|
215
|
+
// should be disabled.
|
|
216
|
+
if (this._selectedIndexChanged) {
|
|
217
|
+
this._scrollToLabel(this._selectedIndex());
|
|
218
|
+
this._checkScrollingControls();
|
|
219
|
+
this._selectedIndexChanged = false;
|
|
220
|
+
this._changeDetectorRef.markForCheck();
|
|
221
|
+
}
|
|
222
|
+
// If the scroll distance has been changed (tab selected, focused, scroll controls activated),
|
|
223
|
+
// then translate the header to reflect this.
|
|
224
|
+
if (this._scrollDistanceChanged) {
|
|
225
|
+
this._updateTabScrollPosition();
|
|
226
|
+
this._scrollDistanceChanged = false;
|
|
227
|
+
this._changeDetectorRef.markForCheck();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
ngOnDestroy() {
|
|
231
|
+
this._keyManager?.destroy();
|
|
232
|
+
this._destroyed.next();
|
|
233
|
+
this._destroyed.complete();
|
|
234
|
+
this._stopScrolling.complete();
|
|
235
|
+
}
|
|
236
|
+
/** Handles keyboard events on the header. */
|
|
237
|
+
_handleKeydown(event) {
|
|
238
|
+
// We don't handle any key bindings with a modifier key.
|
|
239
|
+
if (hasModifierKey(event)) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
switch (event.keyCode) {
|
|
243
|
+
case ENTER:
|
|
244
|
+
case SPACE:
|
|
245
|
+
if (this.focusIndex !== this._selectedIndex()) {
|
|
246
|
+
const item = this._items()[this.focusIndex];
|
|
247
|
+
if (item && !item.disabled) {
|
|
248
|
+
this.selectFocusedIndex.emit(this.focusIndex);
|
|
249
|
+
this._itemSelected(event);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
break;
|
|
253
|
+
default:
|
|
254
|
+
this._keyManager.onKeydown(event);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Callback for when the MutationObserver detects that the content has changed.
|
|
259
|
+
*/
|
|
260
|
+
_onContentChanges() {
|
|
261
|
+
const textContent = this._elementRef.nativeElement.textContent;
|
|
262
|
+
// We need to diff the text content of the header, because the MutationObserver callback
|
|
263
|
+
// will fire even if the text content didn't change which is inefficient and is prone
|
|
264
|
+
// to infinite loops if a poorly constructed expression is passed in (see #14249).
|
|
265
|
+
if (textContent !== this._currentTextContent) {
|
|
266
|
+
this._currentTextContent = textContent || '';
|
|
267
|
+
// The content observer runs outside the `NgZone` by default, which
|
|
268
|
+
// means that we need to bring the callback back in ourselves.
|
|
269
|
+
this._ngZone.run(() => {
|
|
270
|
+
this.updatePagination();
|
|
271
|
+
this._changeDetectorRef.markForCheck();
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Updates the view whether pagination should be enabled or not.
|
|
277
|
+
*
|
|
278
|
+
* WARNING: Calling this method can be very costly in terms of performance. It should be called
|
|
279
|
+
* as infrequently as possible from outside of the Tabs component as it causes a reflow of the
|
|
280
|
+
* page.
|
|
281
|
+
*/
|
|
282
|
+
updatePagination() {
|
|
283
|
+
this._checkPaginationEnabled();
|
|
284
|
+
this._checkScrollingControls();
|
|
285
|
+
this._updateTabScrollPosition();
|
|
286
|
+
}
|
|
287
|
+
/** Tracks which element has focus; used for keyboard navigation */
|
|
288
|
+
get focusIndex() {
|
|
289
|
+
return this._keyManager ? (this._keyManager.activeItemIndex ?? 0) : 0;
|
|
290
|
+
}
|
|
291
|
+
/** When the focus index is set, we must manually send focus to the correct label */
|
|
292
|
+
set focusIndex(value) {
|
|
293
|
+
if (!this._isValidIndex(value) || this.focusIndex === value || !this._keyManager) {
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
this._keyManager.setActiveItem(value);
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Determines if an index is valid. If the tabs are not ready yet, we assume that the user is
|
|
300
|
+
* providing a valid index and return true.
|
|
301
|
+
*/
|
|
302
|
+
_isValidIndex(index) {
|
|
303
|
+
return this._items() ? !!this._items()[index] : true;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Sets focus on the HTML element for the label wrapper and scrolls it into the view if
|
|
307
|
+
* scrolling is enabled.
|
|
308
|
+
*/
|
|
309
|
+
_setTabFocus(tabIndex) {
|
|
310
|
+
if (this._showPaginationControls()) {
|
|
311
|
+
this._scrollToLabel(tabIndex);
|
|
312
|
+
}
|
|
313
|
+
if (this._items()?.length) {
|
|
314
|
+
this._items()[tabIndex].focus();
|
|
315
|
+
// Do not let the browser manage scrolling to focus the element, this will be handled
|
|
316
|
+
// by using translation. In LTR, the scroll left should be 0. In RTL, the scroll width
|
|
317
|
+
// should be the full width minus the offset width.
|
|
318
|
+
const containerEl = this._tabListContainer().nativeElement;
|
|
319
|
+
const dir = this._getLayoutDirection();
|
|
320
|
+
if (dir === 'ltr') {
|
|
321
|
+
containerEl.scrollLeft = 0;
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
containerEl.scrollLeft = containerEl.scrollWidth - containerEl.offsetWidth;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/** The layout direction of the containing app. */
|
|
329
|
+
_getLayoutDirection() {
|
|
330
|
+
return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';
|
|
331
|
+
}
|
|
332
|
+
/** Performs the CSS transformation on the tab list that will cause the list to scroll. */
|
|
333
|
+
_updateTabScrollPosition() {
|
|
334
|
+
if (this.disablePagination()) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
const scrollDistance = this.scrollDistance;
|
|
338
|
+
const translateX = this._getLayoutDirection() === 'ltr' ? -scrollDistance : scrollDistance;
|
|
339
|
+
// Don't use `translate3d` here because we don't want to create a new layer. A new layer
|
|
340
|
+
// seems to cause flickering and overflow in Internet Explorer. For example, the ink bar
|
|
341
|
+
// and ripples will exceed the boundaries of the visible tab bar.
|
|
342
|
+
// See: https://github.com/angular/components/issues/10276
|
|
343
|
+
// We round the `transform` here, because transforms with sub-pixel precision cause some
|
|
344
|
+
// browsers to blur the content of the element.
|
|
345
|
+
this._tabList().nativeElement.style.transform = `translateX(${Math.round(translateX)}px)`;
|
|
346
|
+
// Setting the `transform` on IE will change the scroll offset of the parent, causing the
|
|
347
|
+
// position to be thrown off in some cases. We have to reset it ourselves to ensure that
|
|
348
|
+
// it doesn't get thrown off. Note that we scope it only to IE and Edge, because messing
|
|
349
|
+
// with the scroll position throws off Chrome 71+ in RTL mode (see #14689).
|
|
350
|
+
if (this._platform.TRIDENT || this._platform.EDGE) {
|
|
351
|
+
this._tabListContainer().nativeElement.scrollLeft = 0;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/** Sets the distance in pixels that the tab header should be transformed in the X-axis. */
|
|
355
|
+
get scrollDistance() {
|
|
356
|
+
return this._scrollDistance;
|
|
357
|
+
}
|
|
358
|
+
set scrollDistance(value) {
|
|
359
|
+
this._scrollTo(value);
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Moves the tab list in the 'before' or 'after' direction (towards the beginning of the list or
|
|
363
|
+
* the end of the list, respectively). The distance to scroll is computed to be a third of the
|
|
364
|
+
* length of the tab list view window.
|
|
365
|
+
*
|
|
366
|
+
* This is an expensive call that forces a layout reflow to compute box and scroll metrics and
|
|
367
|
+
* should be called sparingly.
|
|
368
|
+
*/
|
|
369
|
+
_scrollHeader(direction) {
|
|
370
|
+
const viewLength = this._tabListContainer().nativeElement.offsetWidth;
|
|
371
|
+
// Move the scroll distance one-third the length of the tab list's viewport.
|
|
372
|
+
const scrollAmount = ((direction === 'before' ? -1 : 1) * viewLength) / 3;
|
|
373
|
+
return this._scrollTo(this._scrollDistance + scrollAmount);
|
|
374
|
+
}
|
|
375
|
+
/** Handles click events on the pagination arrows. */
|
|
376
|
+
_handlePaginatorClick(direction) {
|
|
377
|
+
this._stopInterval();
|
|
378
|
+
this._scrollHeader(direction);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Moves the tab list such that the desired tab label (marked by index) is moved into view.
|
|
382
|
+
*
|
|
383
|
+
* This is an expensive call that forces a layout reflow to compute box and scroll metrics and
|
|
384
|
+
* should be called sparingly.
|
|
385
|
+
*/
|
|
386
|
+
_scrollToLabel(labelIndex) {
|
|
387
|
+
if (this.disablePagination()) {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
const selectedLabel = this._items() ? this._items()[labelIndex] : null;
|
|
391
|
+
if (!selectedLabel) {
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
// The view length is the visible width of the tab labels.
|
|
395
|
+
const viewLength = this._tabListContainer().nativeElement.offsetWidth;
|
|
396
|
+
const { offsetLeft, offsetWidth } = selectedLabel.elementRef.nativeElement;
|
|
397
|
+
let labelBeforePos;
|
|
398
|
+
let labelAfterPos;
|
|
399
|
+
if (this._getLayoutDirection() === 'ltr') {
|
|
400
|
+
labelBeforePos = offsetLeft;
|
|
401
|
+
labelAfterPos = labelBeforePos + offsetWidth;
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
labelAfterPos = this._tabListInner().nativeElement.offsetWidth - offsetLeft;
|
|
405
|
+
labelBeforePos = labelAfterPos - offsetWidth;
|
|
406
|
+
}
|
|
407
|
+
const beforeVisiblePos = this.scrollDistance;
|
|
408
|
+
const afterVisiblePos = this.scrollDistance + viewLength;
|
|
409
|
+
if (labelBeforePos < beforeVisiblePos) {
|
|
410
|
+
// Scroll header to move label to the before direction
|
|
411
|
+
this.scrollDistance -= beforeVisiblePos - labelBeforePos;
|
|
412
|
+
}
|
|
413
|
+
else if (labelAfterPos > afterVisiblePos) {
|
|
414
|
+
// Scroll header to move label to the after direction
|
|
415
|
+
this.scrollDistance += Math.min(labelAfterPos - afterVisiblePos, labelBeforePos - beforeVisiblePos);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Evaluate whether the pagination controls should be displayed. If the scroll width of the
|
|
420
|
+
* tab list is wider than the size of the header container, then the pagination controls should
|
|
421
|
+
* be shown.
|
|
422
|
+
*
|
|
423
|
+
* This is an expensive call that forces a layout reflow to compute box and scroll metrics and
|
|
424
|
+
* should be called sparingly.
|
|
425
|
+
*/
|
|
426
|
+
_checkPaginationEnabled() {
|
|
427
|
+
if (this.disablePagination()) {
|
|
428
|
+
this._showPaginationControls.set(false);
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
const isEnabled = this._tabListInner().nativeElement.scrollWidth > this._elementRef.nativeElement.offsetWidth;
|
|
432
|
+
if (!isEnabled) {
|
|
433
|
+
this.scrollDistance = 0;
|
|
434
|
+
}
|
|
435
|
+
if (isEnabled !== this._showPaginationControls()) {
|
|
436
|
+
this._changeDetectorRef.markForCheck();
|
|
437
|
+
}
|
|
438
|
+
this._showPaginationControls.set(isEnabled);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Evaluate whether the before and after controls should be enabled or disabled.
|
|
443
|
+
* If the header is at the beginning of the list (scroll distance is equal to 0) then disable the
|
|
444
|
+
* before button. If the header is at the end of the list (scroll distance is equal to the
|
|
445
|
+
* maximum distance we can scroll), then disable the after button.
|
|
446
|
+
*
|
|
447
|
+
* This is an expensive call that forces a layout reflow to compute box and scroll metrics and
|
|
448
|
+
* should be called sparingly.
|
|
449
|
+
*/
|
|
450
|
+
_checkScrollingControls() {
|
|
451
|
+
if (this.disablePagination()) {
|
|
452
|
+
this._disableScrollAfter = this._disableScrollBefore = true;
|
|
453
|
+
}
|
|
454
|
+
else {
|
|
455
|
+
// Check if the pagination arrows should be activated.
|
|
456
|
+
this._disableScrollBefore = this.scrollDistance === 0;
|
|
457
|
+
this._disableScrollAfter = this.scrollDistance === this._getMaxScrollDistance();
|
|
458
|
+
this._changeDetectorRef.markForCheck();
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Determines what is the maximum length in pixels that can be set for the scroll distance. This
|
|
463
|
+
* is equal to the difference in width between the tab list container and tab header container.
|
|
464
|
+
*
|
|
465
|
+
* This is an expensive call that forces a layout reflow to compute box and scroll metrics and
|
|
466
|
+
* should be called sparingly.
|
|
467
|
+
*/
|
|
468
|
+
_getMaxScrollDistance() {
|
|
469
|
+
const lengthOfTabList = this._tabListInner().nativeElement.scrollWidth;
|
|
470
|
+
const viewLength = this._tabListContainer().nativeElement.offsetWidth;
|
|
471
|
+
return lengthOfTabList - viewLength || 0;
|
|
472
|
+
}
|
|
473
|
+
/** Stops the currently-running paginator interval. */
|
|
474
|
+
_stopInterval() {
|
|
475
|
+
this._stopScrolling.next();
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Handles the user pressing down on one of the paginators.
|
|
479
|
+
* Starts scrolling the header after a certain amount of time.
|
|
480
|
+
* @param direction In which direction the paginator should be scrolled.
|
|
481
|
+
*/
|
|
482
|
+
_handlePaginatorPress(direction, mouseEvent) {
|
|
483
|
+
// Don't start auto scrolling for right mouse button clicks. Note that we shouldn't have to
|
|
484
|
+
// null check the `button`, but we do it so we don't break tests that use fake events.
|
|
485
|
+
if (mouseEvent && mouseEvent.button !== null && mouseEvent.button !== 0) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
// Avoid overlapping timers.
|
|
489
|
+
this._stopInterval();
|
|
490
|
+
// Start a timer after the delay and keep firing based on the interval.
|
|
491
|
+
timer(HEADER_SCROLL_DELAY, HEADER_SCROLL_INTERVAL)
|
|
492
|
+
// Keep the timer going until something tells it to stop or the component is destroyed.
|
|
493
|
+
.pipe(takeUntil(merge(this._stopScrolling, this._destroyed)))
|
|
494
|
+
.subscribe(() => {
|
|
495
|
+
const { maxScrollDistance, distance } = this._scrollHeader(direction);
|
|
496
|
+
// Stop the timer if we've reached the start or the end.
|
|
497
|
+
if (distance === 0 || distance >= maxScrollDistance) {
|
|
498
|
+
this._stopInterval();
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Scrolls the header to a given position.
|
|
504
|
+
* @param position Position to which to scroll.
|
|
505
|
+
* @returns Information on the current scroll distance and the maximum.
|
|
506
|
+
*/
|
|
507
|
+
_scrollTo(position) {
|
|
508
|
+
if (this.disablePagination()) {
|
|
509
|
+
return { maxScrollDistance: 0, distance: 0 };
|
|
510
|
+
}
|
|
511
|
+
const maxScrollDistance = this._getMaxScrollDistance();
|
|
512
|
+
this._scrollDistance = Math.max(0, Math.min(maxScrollDistance, position));
|
|
513
|
+
// Mark that the scroll distance has changed so that after the view is checked, the CSS
|
|
514
|
+
// transformation can move the header.
|
|
515
|
+
this._scrollDistanceChanged = true;
|
|
516
|
+
this._checkScrollingControls();
|
|
517
|
+
return { maxScrollDistance, distance: this._scrollDistance };
|
|
518
|
+
}
|
|
519
|
+
/** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnTabsPaginatedListDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
520
|
+
/** @nocollapse */ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "18.2.5", type: BrnTabsPaginatedListDirective, inputs: { disablePagination: { classPropertyName: "disablePagination", publicName: "disablePagination", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectFocusedIndex: "selectFocusedIndex", indexFocused: "indexFocused" }, ngImport: i0 });
|
|
521
|
+
}
|
|
522
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BrnTabsPaginatedListDirective, decorators: [{
|
|
523
|
+
type: Directive
|
|
524
|
+
}], ctorParameters: () => [] });
|
|
525
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJuLXRhYnMtcGFnaW5hdGVkLWxpc3QuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vbGlicy9icmFpbi90YWJzL3NyYy9saWIvYnJuLXRhYnMtcGFnaW5hdGVkLWxpc3QuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFFSDs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUUsZUFBZSxFQUF3QixNQUFNLG1CQUFtQixDQUFDO0FBQzFFLE9BQU8sRUFBa0IsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbkUsT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDckUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDdEUsT0FBTyxFQUFFLFFBQVEsRUFBRSwrQkFBK0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2xGLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQ04scUJBQXFCLEVBSXJCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsVUFBVSxFQUNWLFFBQVEsRUFDUixNQUFNLEVBR04sZUFBZSxFQUNmLGdCQUFnQixFQUNoQixRQUFRLEVBQ1IsTUFBTSxFQUNOLE1BQU0sRUFDTixLQUFLLEVBQ0wsTUFBTSxFQUNOLE1BQU0sR0FDTixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBaUIsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsRUFBRSxJQUFJLFlBQVksRUFBRSxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDOUcsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFD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biBzaG91bGRlcnMgb2YgZ2lhbnRzIGhlcmUgYW5kIGFkYXB0IHRoZSBpbXBsZW1lbnRhdGlvbiBwcm92aWRlZCBieSB0aGUgaW5jcmVkaWJsZSBBbmd1bGFyXG4gKiB0ZWFtOiBodHRwczovL2dpdGh1Yi5jb20vYW5ndWxhci9jb21wb25lbnRzL2Jsb2IvbWFpbi9zcmMvbWF0ZXJpYWwvdGFicy9wYWdpbmF0ZWQtdGFiLWhlYWRlci50c1xuICogQ2hlY2sgdGhlbSBvdXQhIEdpdmUgdGhlbSBhIHRyeSEgTGVhdmUgYSBzdGFyISBUaGVpciB3b3JrIGlzIGluY3JlZGlibGUhXG4gKi9cblxuLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7IEZvY3VzS2V5TWFuYWdlciwgdHlwZSBGb2N1c2FibGVPcHRpb24gfSBmcm9tICdAYW5ndWxhci9jZGsvYTExeSc7XG5pbXBvcnQgeyB0eXBlIERpcmVjdGlvbiwgRGlyZWN0aW9uYWxpdHkgfSBmcm9tICdAYW5ndWxhci9jZGsvYmlkaSc7XG5pbXBvcnQgeyBFTlRFUiwgU1BBQ0UsIGhhc01vZGlmaWVyS2V5IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2tleWNvZGVzJztcbmltcG9ydCB7IFNoYXJlZFJlc2l6ZU9ic2VydmVyIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL29ic2VydmVycy9wcml2YXRlJztcbmltcG9ydCB7IFBsYXRmb3JtLCBub3JtYWxpemVQYXNzaXZlTGlzdGVuZXJPcHRpb25zIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3BsYXRmb3JtJztcbmltcG9ydCB7IFZpZXdwb3J0UnVsZXIgfSBmcm9tICdAYW5ndWxhci9jZGsvc2Nyb2xsaW5nJztcbmltcG9ydCB7XG5cdEFOSU1BVElPTl9NT0RVTEVfVFlQRSxcblx0dHlwZSBBZnRlckNvbnRlbnRDaGVja2VkLFxuXHR0eXBlIEFmdGVyQ29udGVudEluaXQsXG5cdHR5cGUgQWZ0ZXJWaWV3SW5pdCxcblx0Q2hhbmdlRGV0ZWN0b3JSZWYsXG5cdERpcmVjdGl2ZSxcblx0RWxlbWVudFJlZixcblx0SW5qZWN0b3IsXG5cdE5nWm9uZSxcblx0dHlwZSBPbkRlc3Ryb3ksXG5cdFNpZ25hbCxcblx0YWZ0ZXJOZXh0UmVuZGVyLFxuXHRib29sZWFuQXR0cmlidXRlLFxuXHRjb21wdXRlZCxcblx0ZWZmZWN0LFxuXHRpbmplY3QsXG5cdGlucHV0LFxuXHRvdXRwdXQsXG5cdHNpZ25hbCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBFTVBUWSwgT2JzZXJ2YWJsZSwgdHlwZSBPYnNlcnZlciwgU3ViamVjdCwgZnJvbUV2ZW50LCBtZXJnZSwgb2YgYXMgb2JzZXJ2YWJsZU9mLCB0aW1lciB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBmaWx0ZXIsIHNraXAsIHN0YXJ0V2l0aCwgc3dpdGNoTWFwLCB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBCcm5UYWJzRGlyZWN0aXZlIH0gZnJvbSAnLi9icm4tdGFicy10cmlnZ2VyLmRpcmVjdGl2ZSc7XG5cbi8qKiBDb25maWcgdXNlZCB0byBiaW5kIHBhc3NpdmUgZXZlbnQgbGlzdGVuZXJzICovXG5jb25zdCBwYXNzaXZlRXZlbnRMaXN0ZW5lck9wdGlvbnMgPSBub3JtYWxpemVQYXNzaXZlTGlzdGVuZXJPcHRpb25zKHtcblx0cGFzc2l2ZTogdHJ1ZSxcbn0pIGFzIEV2ZW50TGlzdGVuZXJPcHRpb25zO1xuXG4vKipcbiAqIFRoZSBkaXJlY3Rpb25zIHRoYXQgc2Nyb2xsaW5nIGNhbiBnbyBpbiB3aGVuIHRoZSBoZWFkZXIncyB0YWJzIGV4Y2VlZCB0aGUgaGVhZGVyIHdpZHRoLiAnQWZ0ZXInXG4gKiB3aWxsIHNjcm9sbCB0aGUgaGVhZGVyIHRvd2FyZHMgdGhlIGVuZCBvZiB0aGUgdGFicyBsaXN0IGFuZCAnYmVmb3JlJyB3aWxsIHNjcm9sbCB0b3dhcmRzIHRoZVxuICogYmVnaW5uaW5nIG9mIHRoZSBsaXN0LlxuICovXG5leHBvcnQgdHlwZSBTY3JvbGxEaXJlY3Rpb24gPSAnYWZ0ZXInIHwgJ2JlZm9yZSc7XG5cbi8qKlxuICogQW1vdW50IG9mIG1pbGxpc2Vjb25kcyB0byB3YWl0IGJlZm9yZSBzdGFydGluZyB0byBzY3JvbGwgdGhlIGhlYWRlciBhdXRvbWF0aWNhbGx5LlxuICogU2V0IGEgbGl0dGxlIGNvbnNlcnZhdGl2ZWx5IGluIG9yZGVyIHRvIGhhbmRsZSBmYWtlIGV2ZW50cyBkaXNwYXRjaGVkIG9uIHRvdWNoIGRldmljZXMuXG4gKi9cbmNvbnN0IEhFQURFUl9TQ1JPTExfREVMQVkgPSA2NTA7XG5cbi8qKlxuICogSW50ZXJ2YWwgaW4gbWlsbGlzZWNvbmRzIGF0IHdoaWNoIHRvIHNjcm9sbCB0aGUgaGVhZGVyXG4gKiB3aGlsZSB0aGUgdXNlciBpcyBob2xkaW5nIHRoZWlyIHBvaW50ZXIuXG4gKi9cbmNvbnN0IEhFQURFUl9TQ1JPTExfSU5URVJWQUwgPSAxMDA7XG5cbi8qKiBJdGVtIGluc2lkZSBhIHBhZ2luYXRlZCB0YWIgaGVhZGVyLiAqL1xuZXhwb3J0IHR5cGUgQnJuUGFnaW5hdGVkVGFiSGVhZGVySXRlbSA9IEZvY3VzYWJsZU9wdGlvbiAmIHsgZWxlbWVudFJlZjogRWxlbWVudFJlZiB9O1xuXG4vKipcbiAqIEJhc2UgY2xhc3MgZm9yIGEgdGFiIGhlYWRlciB0aGF0IHN1cHBvcnRlZCBwYWdpbmF0aW9uLlxuICogQGRvY3MtcHJpdmF0ZVxuICovXG5ARGlyZWN0aXZlKClcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCcm5UYWJzUGFnaW5hdGVkTGlzdERpcmVjdGl2ZVxuXHRpbXBsZW1lbnRzIEFmdGVyQ29udGVudENoZWNrZWQsIEFmdGVyQ29udGVudEluaXQsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveVxue1xuXHRwdWJsaWMgYWJzdHJhY3QgX2l0ZW1zOiBTaWduYWw8UmVhZG9ubHlBcnJheTxCcm5QYWdpbmF0ZWRUYWJIZWFkZXJJdGVtPj47XG5cdHB1YmxpYyBhYnN0cmFjdCBfaXRlbXNDaGFuZ2VzOiBPYnNlcnZhYmxlPFJlYWRvbmx5QXJyYXk8QnJuUGFnaW5hdGVkVGFiSGVhZGVySXRlbT4+O1xuXHRwdWJsaWMgYWJzdHJhY3QgX3RhYkxpc3RDb250YWluZXI6IFNpZ25hbDxFbGVtZW50UmVmPEhUTUxFbGVtZW50Pj47XG5cdHB1YmxpYyBhYnN0cmFjdCBfdGFiTGlzdDogU2lnbmFsPEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+Pjtcblx0cHVibGljIGFic3RyYWN0IF90YWJMaXN0SW5uZXI6IFNpZ25hbDxFbGVtZW50UmVmPEhUTUxFbGVtZW50Pj47XG5cdHB1YmxpYyBhYnN0cmFjdCBfbmV4dFBhZ2luYXRvcjogU2lnbmFsPEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+Pjtcblx0cHVibGljIGFic3RyYWN0IF9wcmV2aW91c1BhZ2luYXRvcjogU2lnbmFsPEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+PjtcblxuXHQvKiogVGhlIGRpc3RhbmNlIGluIHBpeGVscyB0aGF0IHRoZSB0YWIgbGFiZWxzIHNob3VsZCBiZSB0cmFuc2xhdGVkIHRvIHRoZSBsZWZ0LiAqL1xuXHRwcml2YXRlIF9zY3JvbGxEaXN0YW5jZSA9IDA7XG5cblx0LyoqIFdoZXRoZXIgdGhlIGhlYWRlciBzaG91bGQgc2Nyb2xsIHRvIHRoZSBzZWxlY3RlZCBpbmRleCBhZnRlciB0aGUgdmlldyBoYXMgYmVlbiBjaGVja2VkLiAqL1xuXHRwcml2YXRlIF9zZWxlY3RlZEluZGV4Q2hhbmdlZCA9IGZhbHNlO1xuXG5cdHByaXZhdGUgcmVhZG9ubHkgX3Jvb3QgPSBpbmplY3QoQnJuVGFic0RpcmVjdGl2ZSk7XG5cdHByaXZhdGUgcmVhZG9ubHkgX2FjdGl2ZVRhYiA9IHRoaXMuX3Jvb3QuJGFjdGl2ZVRhYjtcblx0cHJpdmF0ZSByZWFkb25seSBfdGFicyA9IHRoaXMuX3Jvb3QuJHRhYnM7XG5cblx0LyoqIEVtaXRzIHdoZW4gdGhlIGNvbXBvbmVudCBpcyBkZXN0cm95ZWQuICovXG5cdHByb3RlY3RlZCByZWFkb25seSBfZGVzdHJveWVkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuXHQvKiogV2hldGhlciB0aGUgY29udHJvbHMgZm9yIHBhZ2luYXRpb24gc2hvdWxkIGJlIGRpc3BsYXllZCAqL1xuXHRwdWJsaWMgX3Nob3dQYWdpbmF0aW9uQ29udHJvbHMgPSBzaWduYWwoZmFsc2UpO1xuXG5cdC8qKiBXaGV0aGVyIHRoZSB0YWIgbGlzdCBjYW4gYmUgc2Nyb2xsZWQgbW9yZSB0b3dhcmRzIHRoZSBlbmQgb2YgdGhlIHRhYiBsYWJlbCBsaXN0LiAqL1xuXHRwdWJsaWMgX2Rpc2FibGVTY3JvbGxBZnRlciA9IHRydWU7XG5cblx0LyoqIFdoZXRoZXIgdGhlIHRhYiBsaXN0IGNhbiBiZSBzY3JvbGxlZCBtb3JlIHRvd2FyZHMgdGhlIGJlZ2lubmluZyBvZiB0aGUgdGFiIGxhYmVsIGxpc3QuICovXG5cdHB1YmxpYyBfZGlzYWJsZVNjcm9sbEJlZm9yZSA9IHRydWU7XG5cblx0LyoqXG5cdCAqIFRoZSBudW1iZXIgb2YgdGFiIGxhYmVscyB0aGF0IGFyZSBkaXNwbGF5ZWQgb24gdGhlIGhlYWRlci4gV2hlbiB0aGlzIGNoYW5nZXMsIHRoZSBoZWFkZXJcblx0ICogc2hvdWxkIHJlLWV2YWx1YXRlIHRoZSBzY3JvbGwgcG9zaXRpb24uXG5cdCAqL1xuXHRwcml2YXRlIF90YWJMYWJlbENvdW50ITogbnVtYmVyO1xuXG5cdC8qKiBXaGV0aGVyIHRoZSBzY3JvbGwgZGlzdGFuY2UgaGFzIGNoYW5nZWQgYW5kIHNob3VsZCBiZSBhcHBsaWVkIGFmdGVyIHRoZSB2aWV3IGlzIGNoZWNrZWQuICovXG5cdHByaXZhdGUgX3Njcm9sbERpc3RhbmNlQ2hhbmdlZCE6IGJvb2xlYW47XG5cblx0LyoqIFVzZWQgdG8gbWFuYWdlIGZvY3VzIGJldHdlZW4gdGhlIHRhYnMuICovXG5cdHByaXZhdGUgX2tleU1hbmFnZXIhOiBGb2N1c0tleU1hbmFnZXI8QnJuUGFnaW5hdGVkVGFiSGVhZGVySXRlbT47XG5cblx0LyoqIENhY2hlZCB0ZXh0IGNvbnRlbnQgb2YgdGhlIGhlYWRlci4gKi9cblx0cHJpdmF0ZSBfY3VycmVudFRleHRDb250ZW50ITogc3RyaW5nO1xuXG5cdC8qKiBTdHJlYW0gdGhhdCB3aWxsIHN0b3AgdGhlIGF1dG9tYXRlZCBzY3JvbGxpbmcuICovXG5cdHByaXZhdGUgcmVhZG9ubHkgX3N0b3BTY3JvbGxpbmcgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG5cdC8qKlxuXHQgKiBXaGV0aGVyIHBhZ2luYXRpb24gc2hvdWxkIGJlIGRpc2FibGVkLiBUaGlzIGNhbiBiZSB1c2VkIHRvIGF2b2lkIHVubmVjZXNzYXJ5XG5cdCAqIGxheW91dCByZWNhbGN1bGF0aW9ucyBpZiBpdCdzIGtub3duIHRoYXQgcGFnaW5hdGlvbiB3b24ndCBiZSByZXF1aXJlZC5cblx0ICovXG5cdHB1YmxpYyBkaXNhYmxlUGFnaW5hdGlvbiA9IGlucHV0KGZhbHNlLCB7IHRyYW5zZm9ybTogYm9vbGVhbkF0dHJpYnV0ZSB9KTtcblxuXHQvKiogVGhlIGluZGV4IG9mIHRoZSBhY3RpdmUgdGFiLiAqL1xuXHRwcml2YXRlIHJlYWRvbmx5IF9zZWxlY3RlZEluZGV4ID0gY29tcHV0ZWQoKCkgPT4ge1xuXHRcdGNvbnN0IGN1cnJlbnRUYWJLZXkgPSB0aGlzLl9hY3RpdmVUYWIoKTtcblx0XHRjb25zdCB0YWJzID0gdGhpcy5fdGFicygpO1xuXG5cdFx0bGV0IGFjdGl2ZUluZGV4ID0gMDtcblx0XHRpZiAoY3VycmVudFRhYktleSAmJiB0aGlzLl9pdGVtcygpKSB7XG5cdFx0XHRjb25zdCBjdXJyZW50VGFiID0gdGFic1tjdXJyZW50VGFiS2V5XTtcblx0XHRcdGlmIChjdXJyZW50VGFiKSB7XG5cdFx0XHRcdGFjdGl2ZUluZGV4ID0gdGhpcy5faXRlbXMoKS5pbmRleE9mKGN1cnJlbnRUYWIudHJpZ2dlcik7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGFjdGl2ZUluZGV4O1xuXHR9KTtcblxuXHQvKiogRXZlbnQgZW1pdHRlZCB3aGVuIHRoZSBvcHRpb24gaXMgc2VsZWN0ZWQuICovXG5cdHB1YmxpYyByZWFkb25seSBzZWxlY3RGb2N1c2VkSW5kZXggPSBvdXRwdXQ8bnVtYmVyPigpO1xuXG5cdC8qKiBFdmVudCBlbWl0dGVkIHdoZW4gYSBsYWJlbCBpcyBmb2N1c2VkLiAqL1xuXHRwdWJsaWMgcmVhZG9ubHkgaW5kZXhGb2N1c2VkID0gb3V0cHV0PG51bWJlcj4oKTtcblxuXHRwcml2YXRlIHJlYWRvbmx5IF9zaGFyZWRSZXNpemVPYnNlcnZlciA9IGluamVjdChTaGFyZWRSZXNpemVPYnNlcnZlcik7XG5cblx0cHJpdmF0ZSByZWFkb25seSBfaW5qZWN0b3IgPSBpbmplY3QoSW5qZWN0b3IpO1xuXG5cdHByb3RlY3RlZCBfZWxlbWVudFJlZjogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4gPSBpbmplY3QoRWxlbWVudFJlZik7XG5cdHByb3RlY3RlZCBfY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcblx0cHJpdmF0ZSByZWFkb25seSBfdmlld3BvcnRSdWxlcjogVmlld3BvcnRSdWxlciA9IGluamVjdChWaWV3cG9ydFJ1bGVyKTtcblx0cHJpdmF0ZSByZWFkb25seSBfZGlyID0gaW5qZWN0KERpcmVjdGlvbmFsaXR5LCB7IG9wdGlvbmFsOiB0cnVlIH0pO1xuXHRwcml2YXRlIHJlYWRvbmx5IF9uZ1pvbmU6IE5nWm9uZSA9IGluamVjdChOZ1pvbmUpO1xuXHRwcml2YXRlIHJlYWRvbmx5IF9wbGF0Zm9ybTogUGxhdGZvcm0gPSBpbmplY3QoUGxhdGZvcm0pO1xuXHRwdWJsaWMgX2FuaW1hdGlvbk1vZGUgPSBpbmplY3QoQU5JTUFUSU9OX01PRFVMRV9UWVBFLCB7IG9wdGlvbmFsOiB0cnVlIH0pO1xuXG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdC8vIEJpbmQgdGhlIGBtb3VzZWxlYXZlYCBldmVudCBvbiB0aGUgb3V0c2lkZSBzaW5jZSBpdCBkb2Vzbid0IGNoYW5nZSBhbnl0aGluZyBpbiB0aGUgdmlldy5cblx0XHR0aGlzLl9uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuXHRcdFx0ZnJvbUV2ZW50KHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ21vdXNlbGVhdmUnKVxuXHRcdFx0XHQucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveWVkKSlcblx0XHRcdFx0LnN1YnNjcmliZSgoKSA9PiB7XG5cdFx0XHRcdFx0dGhpcy5fc3RvcEludGVydmFsKCk7XG5cdFx0XHRcdH0pO1xuXHRcdH0pO1xuXG5cdFx0ZWZmZWN0KCgpID0+IHtcblx0XHRcdGNvbnN0IHNlbGVjdGVkSW5kZXggPSB0aGlzLl9zZWxlY3RlZEluZGV4KCk7XG5cblx0XHRcdGlmIChzZWxlY3RlZEluZGV4ICE9PSAwKSB7XG5cdFx0XHRcdHRoaXMuX3NlbGVjdGVkSW5kZXhDaGFuZ2VkID0gdHJ1ZTtcblx0XHRcdFx0aWYgKHRoaXMuX2tleU1hbmFnZXIpIHtcblx0XHRcdFx0XHR0aGlzLl9rZXlNYW5hZ2VyLnVwZGF0ZUFjdGl2ZUl0ZW0oc2VsZWN0ZWRJbmRleCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblx0fVxuXG5cdC8qKiBDYWxsZWQgd2hlbiB0aGUgdXNlciBoYXMgc2VsZWN0ZWQgYW4gaXRlbSB2aWEgdGhlIGtleWJvYXJkLiAqL1xuXHRwcm90ZWN0ZWQgYWJzdHJhY3QgX2l0ZW1TZWxlY3RlZChldmVudDogS2V5Ym9hcmRFdmVudCk6IHZvaWQ7XG5cblx0bmdBZnRlclZpZXdJbml0KCkge1xuXHRcdC8vIFdlIG5lZWQgdG8gaGFuZGxlIHRoZXNlIGV2ZW50cyBtYW51YWxseSwgYmVjYXVzZSB3ZSB3YW50IHRvIGJpbmQgcGFzc2l2ZSBldmVudCBsaXN0ZW5lcnMuXG5cdFx0ZnJvbUV2ZW50KHRoaXMuX3ByZXZpb3VzUGFnaW5hdG9yKCkubmF0aXZlRWxlbWVudCwgJ3RvdWNoc3RhcnQnLCBwYXNzaXZlRXZlbnRMaXN0ZW5lck9wdGlvbnMpXG5cdFx0XHQucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveWVkKSlcblx0XHRcdC5zdWJzY3JpYmUoKCkgPT4ge1xuXHRcdFx0XHR0aGlzLl9oYW5kbGVQYWdpbmF0b3JQcmVzcygnYmVmb3JlJyk7XG5cdFx0XHR9KTtcblxuXHRcdGZyb21FdmVudCh0aGlzLl9uZXh0UGFnaW5hdG9yKCkubmF0aXZlRWxlbWVudCwgJ3RvdWNoc3RhcnQnLCBwYXNzaXZlRXZlbnRMaXN0ZW5lck9wdGlvbnMpXG5cdFx0XHQucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveWVkKSlcblx0XHRcdC5zdWJzY3JpYmUoKCkgPT4ge1xuXHRcdFx0XHR0aGlzLl9oYW5kbGVQYWdpbmF0b3JQcmVzcygnYWZ0ZXInKTtcblx0XHRcdH0pO1xuXHR9XG5cblx0bmdBZnRlckNvbnRlbnRJbml0KCkge1xuXHRcdGNvbnN0IGRpckNoYW5nZSA9IHRoaXMuX2RpciA/IHRoaXMuX2Rpci5jaGFuZ2UgOiBvYnNlcnZhYmxlT2YoJ2x0cicpO1xuXHRcdC8vIFdlIG5lZWQgdG8gZGVib3VuY2UgcmVzaXplIGV2ZW50cyBiZWNhdXNlIHRoZSBhbGlnbm1lbnQgbG9naWMgaXMgZXhwZW5zaXZlLlxuXHRcdC8vIElmIHNvbWVvbmUgYW5pbWF0ZXMgdGhlIHdpZHRoIG9mIHRhYnMsIHdlIGRvbid0IHdhbnQgdG8gcmVhbGlnbiBvbiBldmVyeSBhbmltYXRpb24gZnJhbWUuXG5cdFx0Ly8gT25jZSB3ZSBoYXZlbid0IHNlZW4gYW55IG1vcmUgcmVzaXplIGV2ZW50cyBpbiB0aGUgbGFzdCAzMm1zICh+MiBhbmltYWlvbiBmcmFtZXMpIHdlIGNhblxuXHRcdC8vIHJlLWFsaWduLlxuXHRcdGNvbnN0IHJlc2l6ZSA9IHRoaXMuX3NoYXJlZFJlc2l6ZU9ic2VydmVyXG5cdFx0XHQub2JzZXJ2ZSh0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpXG5cdFx0XHQucGlwZShkZWJvdW5jZVRpbWUoMzIpLCB0YWtlVW50aWwodGhpcy5fZGVzdHJveWVkKSk7XG5cdFx0Ly8gTm90ZTogV2UgZG8gbm90IGFjdHVhbGx5IG5lZWQgdG8gd2F0Y2ggdGhlc2UgZXZlbnRzIGZvciBwcm9wZXIgZnVuY3Rpb25pbmcgb2YgdGhlIHRhYnMsXG5cdFx0Ly8gdGhlIHJlc2l6ZSBldmVudHMgYWJvdmUgc2hvdWxkIGNhcHR1cmUgYW55IHZpZXdwb3J0IHJlc2l6ZSB0aGF0IHdlIGNhcmUgYWJvdXQuIEhvd2V2ZXIsXG5cdFx0Ly8gcmVtb3ZpbmcgdGhpcyBpcyBmYWlybHkgYnJlYWtpbmcgZm9yIHNjcmVlbnNob3QgdGVzdHMsIHNvIHdlJ3JlIGxlYXZpbmcgaXQgaGVyZSBmb3Igbm93LlxuXHRcdGNvbnN0IHZpZXdwb3J0UmVzaXplID0gdGhpcy5fdmlld3BvcnRSdWxlci5jaGFuZ2UoMTUwKS5waXBlKHRha2VVbnRpbCh0aGlzLl9kZXN0cm95ZWQpKTtcblxuXHRcdGNvbnN0IHJlYWxpZ24gPSAoKSA9PiB7XG5cdFx0XHR0aGlzLnVwZGF0ZVBhZ2luYXRpb24oKTtcblx0XHR9O1xuXG5cdFx0dGhpcy5fa2V5TWFuYWdlciA9IG5ldyBGb2N1c0tleU1hbmFnZXI8QnJuUGFnaW5hdGVkVGFiSGVhZGVySXRlbT4odGhpcy5faXRlbXMoKSlcblx0XHRcdC53aXRoSG9yaXpvbnRhbE9yaWVudGF0aW9uKHRoaXMuX2dldExheW91dERpcmVjdGlvbigpKVxuXHRcdFx0LndpdGhIb21lQW5kRW5kKClcblx0XHRcdC53aXRoV3JhcCgpXG5cdFx0XHQvLyBBbGxvdyBmb2N1cyB0byBsYW5kIG9uIGRpc2FibGVkIHRhYnMsIGFzIHBlciBodHRwczovL3czYy5naXRodWIuaW8vYXJpYS1wcmFjdGljZXMvI2tiZF9kaXNhYmxlZF9jb250cm9sc1xuXHRcdFx0LnNraXBQcmVkaWNhdGUoKCkgPT4gZmFsc2UpO1xuXG5cdFx0dGhpcy5fa2V5TWFuYWdlci51cGRhdGVBY3RpdmVJdGVtKHRoaXMuX3NlbGVjdGVkSW5kZXgoKSk7XG5cblx0XHQvLyBOb3RlOiBXZSBkbyBub3QgbmVlZCB0byByZWFsaWduIGFmdGVyIHRoZSBmaXJzdCByZW5kZXIgZm9yIHByb3BlciBmdW5jdGlvbmluZyBvZiB0aGUgdGFic1xuXHRcdC8vIHRoZSByZXNpemUgZXZlbnRzIGFib3ZlIHNob3VsZCBmaXJlIHdoZW4gd2UgZmlyc3Qgc3RhcnQgb2JzZXJ2aW5nIHRoZSBlbGVtZW50LiBIb3dldmVyLFxuXHRcdC8vIHJlbW92aW5nIHRoaXMgaXMgZmFpcmx5IGJyZWFraW5nIGZvciBzY3JlZW5zaG90IHRlc3RzLCBzbyB3ZSdyZSBsZWF2aW5nIGl0IGhlcmUgZm9yIG5vdy5cblx0XHRhZnRlck5leHRSZW5kZXIocmVhbGlnbiwgeyBpbmplY3RvcjogdGhpcy5faW5qZWN0b3IgfSk7XG5cblx0XHQvLyBPbiBkaXIgY2hhbmdlIG9yIHJlc2l6ZSwgcmVhbGlnbiB0aGUgaW5rIGJhciBhbmQgdXBkYXRlIHRoZSBvcmllbnRhdGlvbiBvZlxuXHRcdC8vIHRoZSBrZXkgbWFuYWdlciBpZiB0aGUgZGlyZWN0aW9uIGhhcyBjaGFuZ2VkLlxuXHRcdG1lcmdlKGRpckNoYW5nZSwgdmlld3BvcnRSZXNpemUsIHJlc2l6ZSwgdGhpcy5faXRlbXNDaGFuZ2VzLCB0aGlzLl9pdGVtc1Jlc2l6ZWQoKSlcblx0XHRcdC5waXBlKHRha2VVbnRpbCh0aGlzLl9kZXN0cm95ZWQpKVxuXHRcdFx0LnN1YnNjcmliZSgoKSA9PiB7XG5cdFx0XHRcdC8vIFdlIG5lZWQgdG8gZGVmZXIgdGhpcyB0byBnaXZlIHRoZSBicm93c2VyIHNvbWUgdGltZSB0byByZWNhbGN1bGF0ZVxuXHRcdFx0XHQvLyB0aGUgZWxlbWVudCBkaW1lbnNpb25zLiBUaGUgY2FsbCBoYXMgdG8gYmUgd3JhcHBlZCBpbiBgTmdab25lLnJ1bmAsXG5cdFx0XHRcdC8vIGJlY2F1c2UgdGhlIHZpZXdwb3J0IGNoYW5nZSBoYW5kbGVyIHJ1bnMgb3V0c2lkZSBvZiBBbmd1bGFyLlxuXHRcdFx0XHR0aGlzLl9uZ1pvbmUucnVuKCgpID0+IHtcblx0XHRcdFx0XHRQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcblx0XHRcdFx0XHRcdC8vIENsYW1wIHRoZSBzY3JvbGwgZGlzdGFuY2UsIGJlY2F1c2UgaXQgY2FuIGNoYW5nZSB3aXRoIHRoZSBudW1iZXIgb2YgdGFicy5cblx0XHRcdFx0XHRcdHRoaXMuX3Njcm9sbERpc3RhbmNlID0gTWF0aC5tYXgoMCwgTWF0aC5taW4odGhpcy5fZ2V0TWF4U2Nyb2xsRGlzdGFuY2UoKSwgdGhpcy5fc2Nyb2xsRGlzdGFuY2UpKTtcblx0XHRcdFx0XHRcdHJlYWxpZ24oKTtcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSk7XG5cdFx0XHRcdHRoaXMuX2tleU1hbmFnZXIud2l0aEhvcml6b250YWxPcmllbnRhdGlvbih0aGlzLl9nZXRMYXlvdXREaXJlY3Rpb24oKSk7XG5cdFx0XHR9KTtcblxuXHRcdC8vIElmIHRoZXJlIGlzIGEgY2hhbmdlIGluIHRoZSBmb2N1cyBrZXkgbWFuYWdlciB3ZSBuZWVkIHRvIGVtaXQgdGhlIGBpbmRleEZvY3VzZWRgXG5cdFx0Ly8gZXZlbnQgaW4gb3JkZXIgdG8gcHJvdmlkZSBhIHB1YmxpYyBldmVudCB0aGF0IG5vdGlmaWVzIGFib3V0IGZvY3VzIGNoYW5nZXMuIEFsc28gd2UgcmVhbGlnblxuXHRcdC8vIHRoZSB0YWJzIGNvbnRhaW5lciBieSBzY3JvbGxpbmcgdGhlIG5ldyBmb2N1c2VkIHRhYiBpbnRvIHRoZSB2aXNpYmxlIHNlY3Rpb24uXG5cdFx0dGhpcy5fa2V5TWFuYWdlci5jaGFuZ2Uuc3Vic2NyaWJlKChuZXdGb2N1c0luZGV4KSA9PiB7XG5cdFx0XHR0aGlzLmluZGV4Rm9jdXNlZC5lbWl0KG5ld0ZvY3VzSW5kZXgpO1xuXHRcdFx0dGhpcy5fc2V0VGFiRm9jdXMobmV3Rm9jdXNJbmRleCk7XG5cdFx0fSk7XG5cdH1cblxuXHQvKiogU2VuZHMgYW55IGNoYW5nZXMgdGhhdCBjb3VsZCBhZmZlY3QgdGhlIGxheW91dCBvZiB0aGUgaXRlbXMuICovXG5cdHByaXZhdGUgX2l0ZW1zUmVzaXplZCgpOiBPYnNlcnZhYmxlPFJlc2l6ZU9ic2VydmVyRW50cnlbXT4ge1xuXHRcdGlmICh0eXBlb2YgUmVzaXplT2JzZXJ2ZXIgIT09ICdmdW5jdGlvbicpIHtcblx0XHRcdHJldHVybiBFTVBUWTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5faXRlbXNDaGFuZ2VzLnBpcGUoXG5cdFx0XHRzdGFydFdpdGgodGhpcy5faXRlbXMoKSksXG5cdFx0XHRzd2l0Y2hNYXAoXG5cdFx0XHRcdCh0YWJJdGVtczogUmVhZG9ubHlBcnJheTxCcm5QYWdpbmF0ZWRUYWJIZWFkZXJJdGVtPikgPT5cblx0XHRcdFx0XHRuZXcgT2JzZXJ2YWJsZSgob2JzZXJ2ZXI6IE9ic2VydmVyPFJlc2l6ZU9ic2VydmVyRW50cnlbXT4pID0+XG5cdFx0XHRcdFx0XHR0aGlzLl9uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuXHRcdFx0XHRcdFx0XHRjb25zdCByZXNpemVPYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoZW50cmllcykgPT4gb2JzZXJ2ZXIubmV4dChlbnRyaWVzKSk7XG5cdFx0XHRcdFx0XHRcdGZvciAoY29uc3QgdGFiSXRlbSBvZiB0YWJJdGVtcykge1xuXHRcdFx0XHRcdFx0XHRcdHJlc2l6ZU9ic2VydmVyLm9ic2VydmUodGFiSXRlbS5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdHJldHVybiAoKSA9PiB7XG5cdFx0XHRcdFx0XHRcdFx0cmVzaXplT2JzZXJ2ZXIuZGlzY29ubmVjdCgpO1xuXHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0fSksXG5cdFx0XHRcdFx0KSxcblx0XHRcdCksXG5cdFx0XHQvLyBTa2lwIHRoZSBmaXJzdCBlbWl0IHNpbmNlIHRoZSByZXNpemUgb2JzZXJ2ZXIgZW1pdHMgd2hlbiBhbiBpdGVtXG5cdFx0XHQvLyBpcyBvYnNlcnZlZCBmb3IgbmV3IGl0ZW1zIHdoZW4gdGhlIHRhYiBpcyBhbHJlYWR5IGluc2VydGVkXG5cdFx0XHRza2lwKDEpLFxuXHRcdFx0Ly8gU2tpcCBlbWlzc2lvbnMgd2hlcmUgYWxsIHRoZSBlbGVtZW50cyBhcmUgaW52aXNpYmxlIHNpbmNlIHdlIGRvbid0IHdhbnRcblx0XHRcdC8vIHRoZSBoZWFkZXIgdG8gdHJ5IGFuZCByZS1yZW5kZXIgd2l0aCBpbnZhbGlkIG1lYXN1cmVtZW50cy4gU2VlICMyNTU3NC5cblx0XHRcdGZpbHRlcigoZW50cmllcykgPT4gZW50cmllcy5zb21lKChlKSA9PiBlLmNvbnRlbnRSZWN0LndpZHRoID4gMCAmJiBlLmNvbnRlbnRSZWN0LmhlaWdodCA+IDApKSxcblx0XHQpO1xuXHR9XG5cblx0bmdBZnRlckNvbnRlbnRDaGVja2VkKCk6IHZvaWQge1xuXHRcdC8vIElmIHRoZSBudW1iZXIgb2YgdGFiIGxhYmVscyBoYXZlIGNoYW5nZWQsIGNoZWNrIGlmIHNjcm9sbGluZyBzaG91bGQgYmUgZW5hYmxlZFxuXHRcdGlmICh0aGlzLl90YWJMYWJlbENvdW50ICE9PSB0aGlzLl9pdGVtcygpLmxlbmd0aCkge1xuXHRcdFx0dGhpcy51cGRhdGVQYWdpbmF0aW9uKCk7XG5cdFx0XHR0aGlzLl90YWJMYWJlbENvdW50ID0gdGhpcy5faXRlbXMoKS5sZW5ndGg7XG5cdFx0XHR0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcblx0XHR9XG5cblx0XHQvLyBJZiB0aGUgc2VsZWN0ZWQgaW5kZXggaGFzIGNoYW5nZWQsIHNjcm9sbCB0byB0aGUgbGFiZWwgYW5kIGNoZWNrIGlmIHRoZSBzY3JvbGxpbmcgY29udHJvbHNcblx0XHQvLyBzaG91bGQgYmUgZGlzYWJsZWQuXG5cdFx0aWYgKHRoaXMuX3NlbGVjdGVkSW5kZXhDaGFuZ2VkKSB7XG5cdFx0XHR0aGlzLl9zY3JvbGxUb0xhYmVsKHRoaXMuX3NlbGVjdGVkSW5kZXgoKSk7XG5cdFx0XHR0aGlzLl9jaGVja1Njcm9sbGluZ0NvbnRyb2xzKCk7XG5cdFx0XHR0aGlzLl9zZWxlY3RlZEluZGV4Q2hhbmdlZCA9IGZhbHNlO1xuXHRcdFx0dGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG5cdFx0fVxuXG5cdFx0Ly8gSWYgdGhlIHNjcm9sbCBkaXN0YW5jZSBoYXMgYmVlbiBjaGFuZ2VkICh0YWIgc2VsZWN0ZWQsIGZvY3VzZWQsIHNjcm9sbCBjb250cm9scyBhY3RpdmF0ZWQpLFxuXHRcdC8vIHRoZW4gdHJhbnNsYXRlIHRoZSBoZWFkZXIgdG8gcmVmbGVjdCB0aGlzLlxuXHRcdGlmICh0aGlzLl9zY3JvbGxEaXN0YW5jZUNoYW5nZWQpIHtcblx0XHRcdHRoaXMuX3VwZGF0ZVRhYlNjcm9sbFBvc2l0aW9uKCk7XG5cdFx0XHR0aGlzLl9zY3JvbGxEaXN0YW5jZUNoYW5nZWQgPSBmYWxzZTtcblx0XHRcdHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuXHRcdH1cblx0fVxuXG5cdG5nT25EZXN0cm95KCkge1xuXHRcdHRoaXMuX2tleU1hbmFnZXI/LmRlc3Ryb3koKTtcblx0XHR0aGlzLl9kZXN0cm95ZWQubmV4dCgpO1xuXHRcdHRoaXMuX2Rlc3Ryb3llZC5jb21wbGV0ZSgpO1xuXHRcdHRoaXMuX3N0b3BTY3JvbGxpbmcuY29tcGxldGUoKTtcblx0fVxuXG5cdC8qKiBIYW5kbGVzIGtleWJvYXJkIGV2ZW50cyBvbiB0aGUgaGVhZGVyLiAqL1xuXHRfaGFuZGxlS2V5ZG93bihldmVudDogS2V5Ym9hcmRFdmVudCkge1xuXHRcdC8vIFdlIGRvbid0IGhhbmRsZSBhbnkga2V5IGJpbmRpbmdzIHdpdGggYSBtb2RpZmllciBrZXkuXG5cdFx0aWYgKGhhc01vZGlmaWVyS2V5KGV2ZW50KSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHN3aXRjaCAoZXZlbnQua2V5Q29kZSkge1xuXHRcdFx0Y2FzZSBFTlRFUjpcblx0XHRcdGNhc2UgU1BBQ0U6XG5cdFx0XHRcdGlmICh0aGlzLmZvY3VzSW5kZXggIT09IHRoaXMuX3NlbGVjdGVkSW5kZXgoKSkge1xuXHRcdFx0XHRcdGNvbnN0IGl0ZW0gPSB0aGlzLl9pdGVtcygpW3RoaXMuZm9jdXNJbmRleF07XG5cblx0XHRcdFx0XHRpZiAoaXRlbSAmJiAhaXRlbS5kaXNhYmxlZCkge1xuXHRcdFx0XHRcdFx0dGhpcy5zZWxlY3RGb2N1c2VkSW5kZXguZW1pdCh0aGlzLmZvY3VzSW5kZXgpO1xuXHRcdFx0XHRcdFx0dGhpcy5faXRlbVNlbGVjdGVkKGV2ZW50KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHR0aGlzLl9rZXlNYW5hZ2VyLm9uS2V5ZG93bihldmVudCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIENhbGxiYWNrIGZvciB3aGVuIHRoZSBNdXRhdGlvbk9ic2VydmVyIGRldGVjdHMgdGhhdCB0aGUgY29udGVudCBoYXMgY2hhbmdlZC5cblx0ICovXG5cdF9vbkNvbnRlbnRDaGFuZ2VzKCkge1xuXHRcdGNvbnN0IHRleHRDb250ZW50ID0gdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnRleHRDb250ZW50O1xuXG5cdFx0Ly8gV2UgbmVlZCB0byBkaWZmIHRoZSB0ZXh0IGNvbnRlbnQgb2YgdGhlIGhlYWRlciwgYmVjYXVzZSB0aGUgTXV0YXRpb25PYnNlcnZlciBjYWxsYmFja1xuXHRcdC8vIHdpbGwgZmlyZSBldmVuIGlmIHRoZSB0ZXh0IGNvbnRlbnQgZGlkbid0IGNoYW5nZSB3aGljaCBpcyBpbmVmZmljaWVudCBhbmQgaXMgcHJvbmVcblx0XHQvLyB0byBpbmZpbml0ZSBsb29wcyBpZiBhIHBvb3JseSBjb25zdHJ1Y3RlZCBleHByZXNzaW9uIGlzIHBhc3NlZCBpbiAoc2VlICMxNDI0OSkuXG5cdFx0aWYgKHRleHRDb250ZW50ICE9PSB0aGlzLl9jdXJyZW50VGV4dENvbnRlbnQpIHtcblx0XHRcdHRoaXMuX2N1cnJlbnRUZXh0Q29udGVudCA9IHRleHRDb250ZW50IHx8ICcnO1xuXG5cdFx0XHQvLyBUaGUgY29udGVudCBvYnNlcnZlciBydW5zIG91dHNpZGUgdGhlIGBOZ1pvbmVgIGJ5IGRlZmF1bHQsIHdoaWNoXG5cdFx0XHQvLyBtZWFucyB0aGF0IHdlIG5lZWQgdG8gYnJpbmcgdGhlIGNhbGxiYWNrIGJhY2sgaW4gb3Vyc2VsdmVzLlxuXHRcdFx0dGhpcy5fbmdab25lLnJ1bigoKSA9PiB7XG5cdFx0XHRcdHRoaXMudXBkYXRlUGFnaW5hdGlvbigpO1xuXHRcdFx0XHR0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBVcGRhdGVzIHRoZSB2aWV3IHdoZXRoZXIgcGFnaW5hdGlvbiBzaG91bGQgYmUgZW5hYmxlZCBvciBub3QuXG5cdCAqXG5cdCAqIFdBUk5JTkc6IENhbGxpbmcgdGhpcyBtZXRob2QgY2FuIGJlIHZlcnkgY29zdGx5IGluIHRlcm1zIG9mIHBlcmZvcm1hbmNlLiBJdCBzaG91bGQgYmUgY2FsbGVkXG5cdCAqIGFzIGluZnJlcXVlbnRseSBhcyBwb3NzaWJsZSBmcm9tIG91dHNpZGUgb2YgdGhlIFRhYnMgY29tcG9uZW50IGFzIGl0IGNhdXNlcyBhIHJlZmxvdyBvZiB0aGVcblx0ICogcGFnZS5cblx0ICovXG5cdHVwZGF0ZVBhZ2luYXRpb24oKSB7XG5cdFx0dGhpcy5fY2hlY2tQYWdpbmF0aW9uRW5hYmxlZCgpO1xuXHRcdHRoaXMuX2NoZWNrU2Nyb2xsaW5nQ29udHJvbHMoKTtcblx0XHR0aGlzLl91cGRhdGVUYWJTY3JvbGxQb3NpdGlvbigpO1xuXHR9XG5cblx0LyoqIFRyYWNrcyB3aGljaCBlbGVtZW50IGhhcyBmb2N1czsgdXNlZCBmb3Iga2V5Ym9hcmQgbmF2aWdhdGlvbiAqL1xuXHRwdWJsaWMgZ2V0IGZvY3VzSW5kZXgoKTogbnVtYmVyIHtcblx0XHRyZXR1cm4gdGhpcy5fa2V5TWFuYWdlciA/ICh0aGlzLl9rZXlNYW5hZ2VyLmFjdGl2ZUl0ZW1JbmRleCA/PyAwKSA6IDA7XG5cdH1cblxuXHQvKiogV2hlbiB0aGUgZm9jdXMgaW5kZXggaXMgc2V0LCB3ZSBtdXN0IG1hbnVhbGx5IHNlbmQgZm9jdXMgdG8gdGhlIGNvcnJlY3QgbGFiZWwgKi9cblx0cHVibGljIHNldCBmb2N1c0luZGV4KHZhbHVlOiBudW1iZXIpIHtcblx0XHRpZiAoIXRoaXMuX2lzVmFsaWRJbmRleCh2YWx1ZSkgfHwgdGhpcy5mb2N1c0luZGV4ID09PSB2YWx1ZSB8fCAhdGhpcy5fa2V5TWFuYWdlcikge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHRoaXMuX2tleU1hbmFnZXIuc2V0QWN0aXZlSXRlbSh2YWx1ZSk7XG5cdH1cblxuXHQvKipcblx0ICogRGV0ZXJtaW5lcyBpZiBhbiBpbmRleCBpcyB2YWxpZC4gIElmIHRoZSB0YWJzIGFyZSBub3QgcmVhZHkgeWV0LCB3ZSBhc3N1bWUgdGhhdCB0aGUgdXNlciBpc1xuXHQgKiBwcm92aWRpbmcgYSB2YWxpZCBpbmRleCBhbmQgcmV0dXJuIHRydWUuXG5cdCAqL1xuXHRfaXNWYWxpZEluZGV4KGluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcblx0XHRyZXR1cm4gdGhpcy5faXRlbXMoKSA/ICEhdGhpcy5faXRlbXMoKVtpbmRleF0gOiB0cnVlO1xuXHR9XG5cblx0LyoqXG5cdCAqIFNldHMgZm9jdXMgb24gdGhlIEhUTUwgZWxlbWVudCBmb3IgdGhlIGxhYmVsIHdyYXBwZXIgYW5kIHNjcm9sbHMgaXQgaW50byB0aGUgdmlldyBpZlxuXHQgKiBzY3JvbGxpbmcgaXMgZW5hYmxlZC5cblx0ICovXG5cdF9zZXRUYWJGb2N1cyh0YWJJbmRleDogbnVtYmVyKSB7XG5cdFx0aWYgKHRoaXMuX3Nob3dQYWdpbmF0aW9uQ29udHJvbHMoKSkge1xuXHRcdFx0dGhpcy5fc2Nyb2xsVG9MYWJlbCh0YWJJbmRleCk7XG5cdFx0fVxuXG5cdFx0aWYgKHRoaXMuX2l0ZW1zKCk/Lmxlbmd0aCkge1xuXHRcdFx0dGhpcy5faXRlbXMoKVt0YWJJbmRleF0uZm9jdXMoKTtcblxuXHRcdFx0Ly8gRG8gbm90IGxldCB0aGUgYnJvd3NlciBtYW5hZ2Ugc2Nyb2xsaW5nIHRvIGZvY3VzIHRoZSBlbGVtZW50LCB0aGlzIHdpbGwgYmUgaGFuZGxlZFxuXHRcdFx0Ly8gYnkgdXNpbmcgdHJhbnNsYXRpb24uIEluIExUUiwgdGhlIHNjcm9sbCBsZWZ0IHNob3VsZCBiZSAwLiBJbiBSVEwsIHRoZSBzY3JvbGwgd2lkdGhcblx0XHRcdC8vIHNob3VsZCBiZSB0aGUgZnVsbCB3aWR0aCBtaW51cyB0aGUgb2Zmc2V0IHdpZHRoLlxuXHRcdFx0Y29uc3QgY29udGFpbmVyRWwgPSB0aGlzLl90YWJMaXN0Q29udGFpbmVyKCkubmF0aXZlRWxlbWVudDtcblx0XHRcdGNvbnN0IGRpciA9IHRoaXMuX2dldExheW91dERpcmVjdGlvbigpO1xuXG5cdFx0XHRpZiAoZGlyID09PSAnbHRyJykge1xuXHRcdFx0XHRjb250YWluZXJFbC5zY3JvbGxMZWZ0ID0gMDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNvbnRhaW5lckVsLnNjcm9sbExlZnQgPSBjb250YWluZXJFbC5zY3JvbGxXaWR0aCAtIGNvbnRhaW5lckVsLm9mZnNldFdpZHRoO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8qKiBUaGUgbGF5b3V0IGRpcmVjdGlvbiBvZiB0aGUgY29udGFpbmluZyBhcHAuICovXG5cdF9nZXRMYXlvdXREaXJlY3Rpb24oKTogRGlyZWN0aW9uIHtcblx0XHRyZXR1cm4gdGhpcy5fZGlyICYmIHRoaXMuX2Rpci52YWx1ZSA9PT0gJ3J0bCcgPyAncnRsJyA6ICdsdHInO1xuXHR9XG5cblx0LyoqIFBlcmZvcm1zIHRoZSBDU1MgdHJhbnNmb3JtYXRpb24gb24gdGhlIHRhYiBsaXN0IHRoYXQgd2lsbCBjYXVzZSB0aGUgbGlzdCB0byBzY3JvbGwuICovXG5cdF91cGRhdGVUYWJTY3JvbGxQb3NpdGlvbigpIHtcblx0XHRpZiAodGhpcy5kaXNhYmxlUGFnaW5hdGlvbigpKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Y29uc3Qgc2Nyb2xsRGlzdGFuY2UgPSB0aGlzLnNjcm9sbERpc3RhbmNlO1xuXHRcdGNvbnN0IHRyYW5zbGF0ZVggPSB0aGlzLl9nZXRMYXlvdXREaXJlY3Rpb24oKSA9PT0gJ2x0cicgPyAtc2Nyb2xsRGlzdGFuY2UgOiBzY3JvbGxEaXN0YW5jZTtcblxuXHRcdC8vIERvbid0IHVzZSBgdHJhbnNsYXRlM2RgIGhlcmUgYmVjYXVzZSB3ZSBkb24ndCB3YW50IHRvIGNyZWF0ZSBhIG5ldyBsYXllci4gQSBuZXcgbGF5ZXJcblx0XHQvLyBzZWVtcyB0byBjYXVzZSBmbGlja2VyaW5nIGFuZCBvdmVyZmxvdyBpbiBJbnRlcm5ldCBFeHBsb3Jlci4gRm9yIGV4YW1wbGUsIHRoZSBpbmsgYmFyXG5cdFx0Ly8gYW5kIHJpcHBsZXMgd2lsbCBleGNlZWQgdGhlIGJvdW5kYXJpZXMgb2YgdGhlIHZpc2libGUgdGFiIGJhci5cblx0XHQvLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2NvbXBvbmVudHMvaXNzdWVzLzEwMjc2XG5cdFx0Ly8gV2Ugcm91bmQgdGhlIGB0cmFuc2Zvcm1gIGhlcmUsIGJlY2F1c2UgdHJhbnNmb3JtcyB3aXRoIHN1Yi1waXhlbCBwcmVjaXNpb24gY2F1c2Ugc29tZVxuXHRcdC8vIGJyb3dzZXJzIHRvIGJsdXIgdGhlIGNvbnRlbnQgb2YgdGhlIGVsZW1lbnQuXG5cdFx0dGhpcy5fdGFiTGlzdCgpLm5hdGl2ZUVsZW1lbnQuc3R5bGUudHJhbnNmb3JtID0gYHRyYW5zbGF0ZVgoJHtNYXRoLnJvdW5kKHRyYW5zbGF0ZVgpfXB4KWA7XG5cblx0XHQvLyBTZXR0aW5nIHRoZSBgdHJhbnNmb3JtYCBvbiBJRSB3aWxsIGNoYW5nZSB0aGUgc2Nyb2xsIG9mZnNldCBvZiB0aGUgcGFyZW50LCBjYXVzaW5nIHRoZVxuXHRcdC8vIHBvc2l0aW9uIHRvIGJlIHRocm93biBvZmYgaW4gc29tZSBjYXNlcy4gV2UgaGF2ZSB0byByZXNldCBpdCBvdXJzZWx2ZXMgdG8gZW5zdXJlIHRoYXRcblx0XHQvLyBpdCBkb2Vzbid0IGdldCB0aHJvd24gb2ZmLiBOb3RlIHRoYXQgd2Ugc2NvcGUgaXQgb25seSB0byBJRSBhbmQgRWRnZSwgYmVjYXVzZSBtZXNzaW5nXG5cdFx0Ly8gd2l0aCB0aGUgc2Nyb2xsIHBvc2l0aW9uIHRocm93cyBvZmYgQ2hyb21lIDcxKyBpbiBSVEwgbW9kZSAoc2VlICMxNDY4OSkuXG5cdFx0aWYgKHRoaXMuX3BsYXRmb3JtLlRSSURFTlQgfHwgdGhpcy5fcGxhdGZvcm0uRURHRSkge1xuXHRcdFx0dGhpcy5fdGFiTGlzdENvbnRhaW5lcigpLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsTGVmdCA9IDA7XG5cdFx0fVxuXHR9XG5cblx0LyoqIFNldHMgdGhlIGRpc3RhbmNlIGluIHBpeGVscyB0aGF0IHRoZSB0YWIgaGVhZGVyIHNob3VsZCBiZSB0cmFuc2Zvcm1lZCBpbiB0aGUgWC1heGlzLiAqL1xuXHRwdWJsaWMgZ2V0IHNjcm9sbERpc3RhbmNlKCk6IG51bWJlciB7XG5cdFx0cmV0dXJuIHRoaXMuX3Njcm9sbERpc3RhbmNlO1xuXHR9XG5cdHB1YmxpYyBzZXQgc2Nyb2xsRGlzdGFuY2UodmFsdWU6IG51bWJlcikge1xuXHRcdHRoaXMuX3Njcm9sbFRvKHZhbHVlKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBNb3ZlcyB0aGUgdGFiIGxpc3QgaW4gdGhlICdiZWZvcmUnIG9yICdhZnRlcicgZGlyZWN0aW9uICh0b3dhcmRzIHRoZSBiZWdpbm5pbmcgb2YgdGhlIGxpc3Qgb3Jcblx0ICogdGhlIGVuZCBvZiB0aGUgbGlzdCwgcmVzcGVjdGl2ZWx5KS4gVGhlIGRpc3RhbmNlIHRvIHNjcm9sbCBpcyBjb21wdXRlZCB0byBiZSBhIHRoaXJkIG9mIHRoZVxuXHQgKiBsZW5ndGggb2YgdGhlIHRhYiBsaXN0IHZpZXcgd2luZG93LlxuXHQgKlxuXHQgKiBUaGlzIGlzIGFuIGV4cGVuc2l2ZSBjYWxsIHRoYXQgZm9yY2VzIGEgbGF5b3V0IHJlZmxvdyB0byBjb21wdXRlIGJveCBhbmQgc2Nyb2xsIG1ldHJpY3MgYW5kXG5cdCAqIHNob3VsZCBiZSBjYWxsZWQgc3BhcmluZ2x5LlxuXHQgKi9cblx0X3Njcm9sbEhlYWRlcihkaXJlY3Rpb246IFNjcm9sbERpcmVjdGlvbikge1xuXHRcdGNvbnN0IHZpZXdMZW5ndGggPSB0aGlzLl90YWJMaXN0Q29udGFpbmVyKCkubmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aDtcblxuXHRcdC8vIE1vdmUgdGhlIHNjcm9sbCBkaXN0YW5jZSBvbmUtdGhpcmQgdGhlIGxlbmd0aCBvZiB0aGUgdGFiIGxpc3QncyB2aWV3cG9ydC5cblx0XHRjb25zdCBzY3JvbGxBbW91bnQgPSAoKGRpcmVjdGlvbiA9PT0gJ2JlZm9yZScgPyAtMSA6IDEpICogdmlld0xlbmd0aCkgLyAzO1xuXG5cdFx0cmV0dXJuIHRoaXMuX3Njcm9sbFRvKHRoaXMuX3Njcm9sbERpc3RhbmNlICsgc2Nyb2xsQW1vdW50KTtcblx0fVxuXG5cdC8qKiBIYW5kbGVzIGNsaWNrIGV2ZW50cyBvbiB0aGUgcGFnaW5hdGlvbiBhcnJvd3MuICovXG5cdF9oYW5kbGVQYWdpbmF0b3JDbGljayhkaXJlY3Rpb246IFNjcm9sbERpcmVjdGlvbikge1xuXHRcdHRoaXMuX3N0b3BJbnRlcnZhbCgpO1xuXHRcdHRoaXMuX3Njcm9sbEhlYWRlcihkaXJlY3Rpb24pO1xuXHR9XG5cblx0LyoqXG5cdCAqIE1vdmVzIHRoZSB0YWIgbGlzdCBzdWNoIHRoYXQgdGhlIGRlc2lyZWQgdGFiIGxhYmVsIChtYXJrZWQgYnkgaW5kZXgpIGlzIG1vdmVkIGludG8gdmlldy5cblx0ICpcblx0ICogVGhpcyBpcyBhbiBleHBlbnNpdmUgY2FsbCB0aGF0IGZvcmNlcyBhIGxheW91dCByZWZsb3cgdG8gY29tcHV0ZSBib3ggYW5kIHNjcm9sbCBtZXRyaWNzIGFuZFxuXHQgKiBzaG91bGQgYmUgY2FsbGVkIHNwYXJpbmdseS5cblx0ICovXG5cdF9zY3JvbGxUb0xhYmVsKGxhYmVsSW5kZXg6IG51bWJlcikge1xuXHRcdGlmICh0aGlzLmRpc2FibGVQYWdpbmF0aW9uKCkpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRjb25zdCBzZWxlY3RlZExhYmVsID0gdGhpcy5faXRlbXMoKSA/IHRoaXMuX2l0ZW1zKClbbGFiZWxJbmRleF0gOiBudWxsO1xuXG5cdFx0aWYgKCFzZWxlY3RlZExhYmVsKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gVGhlIHZpZXcgbGVuZ3RoIGlzIHRoZSB2aXNpYmxlIHdpZHRoIG9mIHRoZSB0YWIgbGFiZWxzLlxuXHRcdGNvbnN0IHZpZXdMZW5ndGggPSB0aGlzLl90YWJMaXN0Q29udGFpbmVyKCkubmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aDtcblx0XHRjb25zdCB7IG9mZnNldExlZnQsIG9mZnNldFdpZHRoIH0gPSBzZWxlY3RlZExhYmVsLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcblxuXHRcdGxldCBsYWJlbEJlZm9yZVBvczogbnVtYmVyO1xuXHRcdGxldCBsYWJlbEFmdGVyUG9zOiBudW1iZXI7XG5cdFx0aWYgKHRoaXMuX2dldExheW91dERpcmVjdGlvbigpID09PSAnbHRyJykge1xuXHRcdFx0bGFiZWxCZWZvcmVQb3MgPSBvZmZzZXRMZWZ0O1xuXHRcdFx0bGFiZWxBZnRlclBvcyA9IGxhYmVsQmVmb3JlUG9zICsgb2Zmc2V0V2lkdGg7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGxhYmVsQWZ0ZXJQb3MgPSB0aGlzLl90YWJMaXN0SW5uZXIoKS5uYXRpdmVFbGVtZW50Lm9mZnNldFdpZHRoIC0gb2Zmc2V0TGVmdDtcblx0XHRcdGxhYmVsQmVmb3JlUG9zID0gbGFiZWxBZnRlclBvcyAtIG9mZnNldFdpZHRoO1xuXHRcdH1cblxuXHRcdGNvbnN0IGJlZm9yZVZpc2libGVQb3MgPSB0aGlzLnNjcm9sbERpc3RhbmNlO1xuXHRcdGNvbnN0IGFmdGVyVmlzaWJsZVBvcyA9IHRoaXMuc2Nyb2xsRGlzdGFuY2UgKyB2aWV3TGVuZ3RoO1xuXG5cdFx0aWYgKGxhYmVsQmVmb3JlUG9zIDwgYmVmb3JlVmlzaWJsZVBvcykge1xuXHRcdFx0Ly8gU2Nyb2xsIGhlYWRlciB0byBtb3ZlIGxhYmVsIHRvIHRoZSBiZWZvcmUgZGlyZWN0aW9uXG5cdFx0XHR0aGlzLnNjcm9sbERpc3RhbmNlIC09IGJlZm9yZVZpc2libGVQb3MgLSBsYWJlbEJlZm9yZVBvcztcblx0XHR9IGVsc2UgaWYgKGxhYmVsQWZ0ZXJQb3MgPiBhZnRlclZpc2libGVQb3MpIHtcblx0XHRcdC8vIFNjcm9sbCBoZWFkZXIgdG8gbW92ZSBsYWJlbCB0byB0aGUgYWZ0ZXIgZGlyZWN0aW9uXG5cdFx0XHR0aGlzLnNjcm9sbERpc3RhbmNlICs9IE1hdGgubWluKGxhYmVsQWZ0ZXJQb3MgLSBhZnRlclZpc2libGVQb3MsIGxhYmVsQmVmb3JlUG9zIC0gYmVmb3JlVmlzaWJsZVBvcyk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEV2YWx1YXRlIHdoZXRoZXIgdGhlIHBhZ2luYXRpb24gY29udHJvbHMgc2hvdWxkIGJlIGRpc3BsYXllZC4gSWYgdGhlIHNjcm9sbCB3aWR0aCBvZiB0aGVcblx0ICogdGFiIGxpc3QgaXMgd2lkZXIgdGhhbiB0aGUgc2l6ZSBvZiB0aGUgaGVhZGVyIGNvbnRhaW5lciwgdGhlbiB0aGUgcGFnaW5hdGlvbiBjb250cm9scyBzaG91bGRcblx0ICogYmUgc2hvd24uXG5cdCAqXG5cdCAqIFRoaXMgaXMgYW4gZXhwZW5zaXZlIGNhbGwgdGhhdCBmb3JjZXMgYSBsYXlvdXQgcmVmbG93IHRvIGNvbXB1dGUgYm94IGFuZCBzY3JvbGwgbWV0cmljcyBhbmRcblx0ICogc2hvdWxkIGJlIGNhbGxlZCBzcGFyaW5nbHkuXG5cdCAqL1xuXHRfY2hlY2tQYWdpbmF0aW9uRW5hYmxlZCgpIHtcblx0XHRpZiAodGhpcy5kaXNhYmxlUGFnaW5hdGlvbigpKSB7XG5cdFx0XHR0aGlzLl9zaG93UGFnaW5hdGlvbkNvbnRyb2xzLnNldChmYWxzZSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGNvbnN0IGlzRW5hYmxlZCA9IHRoaXMuX3RhYkxpc3RJbm5lcigpLm5hdGl2ZUVsZW1lbnQuc2Nyb2xsV2lkdGggPiB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQub2Zmc2V0V2lkdGg7XG5cblx0XHRcdGlmICghaXNFbmFibGVkKSB7XG5cdFx0XHRcdHRoaXMuc2Nyb2xsRGlzdGFuY2UgPSAwO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoaXNFbmFibGVkICE9PSB0aGlzLl9zaG93UGFnaW5hdGlvbkNvbnRyb2xzKCkpIHtcblx0XHRcdFx0dGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuX3Nob3dQYWdpbmF0aW9uQ29udHJvbHMuc2V0KGlzRW5hYmxlZCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEV2YWx1YXRlIHdoZXRoZXIgdGhlIGJlZm9yZSBhbmQgYWZ0ZXIgY29udHJvbHMgc2hvdWxkIGJlIGVuYWJsZWQgb3IgZGlzYWJsZWQuXG5cdCAqIElmIHRoZSBoZWFkZXIgaXMgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgbGlzdCAoc2Nyb2xsIGRpc3RhbmNlIGlzIGVxdWFsIHRvIDApIHRoZW4gZGlzYWJsZSB0aGVcblx0ICogYmVmb3JlIGJ1dHRvbi4gSWYgdGhlIGhlYWRlciBpcyBhdCB0aGUgZW5kIG9mIHRoZSBsaXN0IChzY3JvbGwgZGlzdGFuY2UgaXMgZXF1YWwgdG8gdGhlXG5cdCAqIG1heGltdW0gZGlzdGFuY2Ugd2UgY2FuIHNjcm9sbCksIHRoZW4gZGlzYWJsZSB0aGUgYWZ0ZXIgYnV0dG9uLlxuXHQgKlxuXHQgKiBUaGlzIGlzIGFuIGV4cGVuc2l2ZSBjYWxsIHRoYXQgZm9yY2VzIGEgbGF5b3V0IHJlZmxvdyB0byBjb21wdXRlIGJveCBhbmQgc2Nyb2xsIG1ldHJpY3MgYW5kXG5cdCAqIHNob3VsZCBiZSBjYWxsZWQgc3BhcmluZ2x5LlxuXHQgKi9cblx0X2NoZWNrU2Nyb2xsaW5nQ29udHJvbHMoKSB7XG5cdFx0aWYgKHRoaXMuZGlzYWJsZVBhZ2luYXRpb24oKSkge1xuXHRcdFx0dGhpcy5fZGlzYWJsZVNjcm9sbEFmdGVyID0gdGhpcy5fZGlzYWJsZVNjcm9sbEJlZm9yZSA9IHRydWU7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIENoZWNrIGlmIHRoZSBwYWdpbmF0aW9uIGFycm93cyBzaG91bGQgYmUgYWN0aXZhdGVkLlxuXHRcdFx0dGhpcy5fZGlzYWJsZVNjcm9sbEJlZm9yZSA9IHRoaXMuc2Nyb2xsRGlzdGFuY2UgPT09IDA7XG5cdFx0XHR0aGlzLl9kaXNhYmxlU2Nyb2xsQWZ0ZXIgPSB0aGlzLnNjcm9sbERpc3RhbmNlID09PSB0aGlzLl9nZXRNYXhTY3JvbGxEaXN0YW5jZSgpO1xuXHRcdFx0dGhpcy5fY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIERldGVybWluZXMgd2hhdCBpcyB0aGUgbWF4aW11bSBsZW5ndGggaW4gcGl4ZWxzIHRoYXQgY2FuIGJlIHNldCBmb3IgdGhlIHNjcm9sbCBkaXN0YW5jZS4gVGhpc1xuXHQgKiBpcyBlcXVhbCB0byB0aGUgZGlmZmVyZW5jZSBpbiB3aWR0aCBiZXR3ZWVuIHRoZSB0YWIgbGlzdCBjb250YWluZXIgYW5kIHRhYiBoZWFkZXIgY29udGFpbmVyLlxuXHQgKlxuXHQgKiBUaGlzIGlzIGFuIGV4cGVuc2l2ZSBjYWxsIHRoYXQgZm9yY2VzIGEgbGF5b3V0IHJlZmxvdyB0byBjb21wdXRlIGJveCBhbmQgc2Nyb2xsIG1ldHJpY3MgYW5kXG5cdCAqIHNob3VsZCBiZSBjYWxsZWQgc3BhcmluZ2x5LlxuXHQgKi9cblx0X2dldE1heFNjcm9sbERpc3RhbmNlKCk6IG51bWJlciB7XG5cdFx0Y29uc3QgbGVuZ3RoT2ZUYWJMaXN0ID0gdGhpcy5fdGFiTGlzdElubmVyKCkubmF0aXZlRWxlbWVudC5zY3JvbGxXaWR0aDtcblx0XHRjb25zdCB2aWV3TGVuZ3RoID0gdGhpcy5fdGFiTGlzdENvbnRhaW5lcigpLm5hdGl2ZUVsZW1lbnQub2Zmc2V0V2lkdGg7XG5cdFx0cmV0dXJuIGxlbmd0aE9mVGFiTGlzdCAtIHZpZXdMZW5ndGggfHwgMDtcblx0fVxuXG5cdC8qKiBTdG9wcyB0aGUgY3VycmVudGx5LXJ1bm5pbmcgcGFnaW5hdG9yIGludGVydmFsLiAgKi9cblx0X3N0b3BJbnRlcnZhbCgpIHtcblx0XHR0aGlzLl9zdG9wU2Nyb2xsaW5nLm5leHQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBIYW5kbGVzIHRoZSB1c2VyIHByZXNzaW5nIGRvd24gb24gb25lIG9mIHRoZSBwYWdpbmF0b3JzLlxuXHQgKiBTdGFydHMgc2Nyb2xsaW5nIHRoZSBoZWFkZXIgYWZ0ZXIgYSBjZXJ0YWluIGFtb3VudCBvZiB0aW1lLlxuXHQgKiBAcGFyYW0gZGlyZWN0aW9uIEluIHdoaWNoIGRpcmVjdGlvbiB0aGUgcGFnaW5hdG9yIHNob3VsZCBiZSBzY3JvbGxlZC5cblx0ICovXG5cdF9oYW5kbGVQYWdpbmF0b3JQcmVzcyhkaXJlY3Rpb246IFNjcm9sbERpcmVjdGlvbiwgbW91c2VFdmVudD86IE1vdXNlRXZlbnQpIHtcblx0XHQvLyBEb24ndCBzdGFydCBhdXRvIHNjcm9sbGluZyBmb3IgcmlnaHQgbW91c2UgYnV0dG9uIGNsaWNrcy4gTm90ZSB0aGF0IHdlIHNob3VsZG4ndCBoYXZlIHRvXG5cdFx0Ly8gbnVsbCBjaGVjayB0aGUgYGJ1dHRvbmAsIGJ1dCB3ZSBkbyBpdCBzbyB3ZSBkb24ndCBicmVhayB0ZXN0cyB0aGF0IHVzZSBmYWtlIGV2ZW50cy5cblx0XHRpZiAobW91c2VFdmVudCAmJiBtb3VzZUV2ZW50LmJ1dHRvbiAhPT0gbnVsbCAmJiBtb3VzZUV2ZW50LmJ1dHRvbiAhPT0gMCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIEF2b2lkIG92ZXJsYXBwaW5nIHRpbWVycy5cblx0XHR0aGlzLl9zdG9wSW50ZXJ2YWwoKTtcblxuXHRcdC8vIFN0YXJ0IGEgdGltZXIgYWZ0ZXIgdGhlIGRlbGF5IGFuZCBrZWVwIGZpcmluZyBiYXNlZCBvbiB0aGUgaW50ZXJ2YWwuXG5cdFx0dGltZXIoSEVBREVSX1NDUk9MTF9ERUxBWSwgSEVBREVSX1NDUk9MTF9JTlRFUlZBTClcblx0XHRcdC8vIEtlZXAgdGhlIHRpbWVyIGdvaW5nIHVudGlsIHNvbWV0aGluZyB0ZWxscyBpdCB0byBzdG9wIG9yIHRoZSBjb21wb25lbnQgaXMgZGVzdHJveWVkLlxuXHRcdFx0LnBpcGUodGFrZVVudGlsKG1lcmdlKHRoaXMuX3N0b3BTY3JvbGxpbmcsIHRoaXMuX2Rlc3Ryb3llZCkpKVxuXHRcdFx0LnN1YnNjcmliZSgoKSA9PiB7XG5cdFx0XHRcdGNvbnN0IHsgbWF4U2Nyb2xsRGlzdGFuY2UsIGRpc3RhbmNlIH0gPSB0aGlzLl9zY3JvbGxIZWFkZXIoZGlyZWN0aW9uKTtcblxuXHRcdFx0XHQvLyBTdG9wIHRoZSB0aW1lciBpZiB3ZSd2ZSByZWFjaGVkIHRoZSBzdGFydCBvciB0aGUgZW5kLlxuXHRcdFx0XHRpZiAoZGlzdGFuY2UgPT09IDAgfHwgZGlzdGFuY2UgPj0gbWF4U2Nyb2xsRGlzdGFuY2UpIHtcblx0XHRcdFx0XHR0aGlzLl9zdG9wSW50ZXJ2YWwoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdH1cblxuXHQvKipcblx0ICogU2Nyb2xscyB0aGUgaGVhZGVyIHRvIGEgZ2l2ZW4gcG9zaXRpb24uXG5cdCAqIEBwYXJhbSBwb3NpdGlvbiBQb3NpdGlvbiB0byB3aGljaCB0byBzY3JvbGwuXG5cdCAqIEByZXR1cm5zIEluZm9ybWF0aW9uIG9uIHRoZSBjdXJyZW50IHNjcm9sbCBkaXN0YW5jZSBhbmQgdGhlIG1heGltdW0uXG5cdCAqL1xuXHRwcml2YXRlIF9zY3JvbGxUbyhwb3NpdGlvbjogbnVtYmVyKSB7XG5cdFx0aWYgKHRoaXMuZGlzYWJsZVBhZ2luYXRpb24oKSkge1xuXHRcdFx0cmV0dXJuIHsgbWF4U2Nyb2xsRGlzdGFuY2U6IDAsIGRpc3RhbmNlOiAwIH07XG5cdFx0fVxuXG5cdFx0Y29uc3QgbWF4U2Nyb2xsRGlzdGFuY2UgPSB0aGlzLl9nZXRNYXhTY3JvbGxEaXN0YW5jZSgpO1xuXHRcdHRoaXMuX3Njcm9sbERpc3RhbmNlID0gTWF0aC5tYXgoMCwgTWF0aC5taW4obWF4U2Nyb2xsRGlzdGFuY2UsIHBvc2l0aW9uKSk7XG5cblx0XHQvLyBNYXJrIHRoYXQgdGhlIHNjcm9sbCBkaXN0YW5jZSBoYXMgY2hhbmdlZCBzbyB0aGF0IGFmdGVyIHRoZSB2aWV3IGlzIGNoZWNrZWQsIHRoZSBDU1Ncblx0XHQvLyB0cmFuc2Zvcm1hdGlvbiBjYW4gbW92ZSB0aGUgaGVhZGVyLlxuXHRcdHRoaXMuX3Njcm9sbERpc3RhbmNlQ2hhbmdlZCA9IHRydWU7XG5cdFx0dGhpcy5fY2hlY2tTY3JvbGxpbmdDb250cm9scygpO1xuXG5cdFx0cmV0dXJuIHsgbWF4U2Nyb2xsRGlzdGFuY2UsIGRpc3RhbmNlOiB0aGlzLl9zY3JvbGxEaXN0YW5jZSB9O1xuXHR9XG59XG4iXX0=
|