@tolle_/tolle-ui 18.2.28 → 18.2.30
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/esm2022/lib/accordion-item.component.mjs +5 -11
- package/esm2022/lib/accordion.component.mjs +4 -9
- package/esm2022/lib/alert-dialog-dynamic.component.mjs +5 -10
- package/esm2022/lib/alert-dialog.component.mjs +44 -59
- package/esm2022/lib/alert.component.mjs +5 -11
- package/esm2022/lib/aspect-ratio.component.mjs +119 -0
- package/esm2022/lib/attachment.component.mjs +334 -0
- package/esm2022/lib/avatar-fallback.component.mjs +3 -3
- package/esm2022/lib/avatar.component.mjs +4 -9
- package/esm2022/lib/badge.component.mjs +4 -9
- package/esm2022/lib/breadcrumb-item.component.mjs +3 -3
- package/esm2022/lib/breadcrumb-link.component.mjs +3 -3
- package/esm2022/lib/breadcrumb-separator.component.mjs +3 -3
- package/esm2022/lib/breadcrumb.component.mjs +3 -3
- package/esm2022/lib/bubble.component.mjs +301 -0
- package/esm2022/lib/button.component.mjs +5 -11
- package/esm2022/lib/calendar.component.mjs +5 -11
- package/esm2022/lib/card.component.mjs +14 -43
- package/esm2022/lib/carousel/carousel.component.mjs +5 -12
- package/esm2022/lib/chain-of-thought.component.mjs +380 -0
- package/esm2022/lib/chart-pie.component.mjs +386 -0
- package/esm2022/lib/chart.component.mjs +1146 -0
- package/esm2022/lib/chart.service.mjs +555 -0
- package/esm2022/lib/checkbox.component.mjs +5 -11
- package/esm2022/lib/checkpoint.component.mjs +134 -0
- package/esm2022/lib/collapsible.component.mjs +4 -11
- package/esm2022/lib/combobox.component.mjs +372 -0
- package/esm2022/lib/command-dialog.component.mjs +164 -0
- package/esm2022/lib/command.component.mjs +514 -0
- package/esm2022/lib/command.service.mjs +130 -0
- package/esm2022/lib/confirmation.component.mjs +219 -0
- package/esm2022/lib/context-menu-trigger.directive.mjs +36 -0
- package/esm2022/lib/context-menu.component.mjs +460 -0
- package/esm2022/lib/context-menu.service.mjs +121 -0
- package/esm2022/lib/context.component.mjs +377 -0
- package/esm2022/lib/conversation.component.mjs +442 -0
- package/esm2022/lib/country-selector.component.mjs +5 -11
- package/esm2022/lib/data-table.component.mjs +63 -12
- package/esm2022/lib/date-picker.component.mjs +251 -198
- package/esm2022/lib/date-range-picker.component.mjs +224 -116
- package/esm2022/lib/date-time-picker.component.mjs +506 -0
- package/esm2022/lib/direction.component.mjs +79 -0
- package/esm2022/lib/dropdown-item.component.mjs +3 -3
- package/esm2022/lib/dropdown-label.component.mjs +3 -3
- package/esm2022/lib/dropdown-menu.component.mjs +3 -3
- package/esm2022/lib/dropdown-separator.component.mjs +3 -3
- package/esm2022/lib/dropdown-trigger.directive.mjs +6 -4
- package/esm2022/lib/empty-state.component.mjs +4 -9
- package/esm2022/lib/field.component.mjs +394 -0
- package/esm2022/lib/hover-card.component.mjs +6 -16
- package/esm2022/lib/inline-citation.component.mjs +263 -0
- package/esm2022/lib/input-group.component.mjs +418 -0
- package/esm2022/lib/input.component.mjs +5 -11
- package/esm2022/lib/item.component.mjs +243 -0
- package/esm2022/lib/kbd.component.mjs +82 -0
- package/esm2022/lib/label.component.mjs +4 -9
- package/esm2022/lib/marker.component.mjs +135 -0
- package/esm2022/lib/masked-input.component.mjs +5 -11
- package/esm2022/lib/menubar.component.mjs +683 -0
- package/esm2022/lib/message-scroller.component.mjs +353 -0
- package/esm2022/lib/message-scroller.service.mjs +157 -0
- package/esm2022/lib/message.component.mjs +228 -0
- package/esm2022/lib/model-selector.component.mjs +310 -0
- package/esm2022/lib/multi-select.component.mjs +155 -72
- package/esm2022/lib/native-select.component.mjs +201 -0
- package/esm2022/lib/navigation-menu.component.mjs +642 -0
- package/esm2022/lib/otp-group.component.mjs +3 -3
- package/esm2022/lib/otp-slot.component.mjs +4 -9
- package/esm2022/lib/otp.component.mjs +5 -11
- package/esm2022/lib/pagination.component.mjs +7 -10
- package/esm2022/lib/plan.component.mjs +335 -0
- package/esm2022/lib/popover-content.component.mjs +4 -9
- package/esm2022/lib/popover.component.mjs +15 -13
- package/esm2022/lib/progress.component.mjs +4 -9
- package/esm2022/lib/prompt-input.component.mjs +526 -0
- package/esm2022/lib/queue.component.mjs +280 -0
- package/esm2022/lib/radio-group.component.mjs +6 -13
- package/esm2022/lib/radio-item.component.mjs +4 -9
- package/esm2022/lib/range-calendar.component.mjs +5 -11
- package/esm2022/lib/reasoning.component.mjs +335 -0
- package/esm2022/lib/resizable.component.mjs +219 -0
- package/esm2022/lib/segment.component.mjs +17 -7
- package/esm2022/lib/select-group.component.mjs +4 -8
- package/esm2022/lib/select-item.component.mjs +4 -9
- package/esm2022/lib/select-separator.component.mjs +4 -8
- package/esm2022/lib/select.component.mjs +133 -49
- package/esm2022/lib/separator.component.mjs +4 -9
- package/esm2022/lib/sheet.component.mjs +38 -56
- package/esm2022/lib/shimmer.component.mjs +84 -0
- package/esm2022/lib/sidebar.component.mjs +11 -1
- package/esm2022/lib/skeleton.component.mjs +4 -9
- package/esm2022/lib/sources.component.mjs +452 -0
- package/esm2022/lib/spinner.component.mjs +68 -0
- package/esm2022/lib/suggestion.component.mjs +207 -0
- package/esm2022/lib/switch.component.mjs +5 -11
- package/esm2022/lib/table.component.mjs +213 -0
- package/esm2022/lib/tabs.component.mjs +4 -11
- package/esm2022/lib/tag-input.component.mjs +5 -11
- package/esm2022/lib/task.component.mjs +359 -0
- package/esm2022/lib/textarea.component.mjs +5 -11
- package/esm2022/lib/theme.service.mjs +17 -6
- package/esm2022/lib/time-picker.component.mjs +923 -0
- package/esm2022/lib/toast.service.mjs +3 -2
- package/esm2022/lib/toaster.component.mjs +76 -39
- package/esm2022/lib/toggle-group.component.mjs +4 -9
- package/esm2022/lib/toggle.component.mjs +5 -11
- package/esm2022/lib/tool.component.mjs +462 -0
- package/esm2022/lib/typography.component.mjs +83 -0
- package/esm2022/lib/utils/color.mjs +140 -19
- package/esm2022/public-api.mjs +61 -1
- package/fesm2022/tolle-ui.mjs +16457 -1024
- package/fesm2022/tolle-ui.mjs.map +1 -1
- package/lib/alert-dialog.component.d.ts +10 -2
- package/lib/aspect-ratio.component.d.ts +20 -0
- package/lib/attachment.component.d.ts +101 -0
- package/lib/bubble.component.d.ts +112 -0
- package/lib/chain-of-thought.component.d.ts +166 -0
- package/lib/chart-pie.component.d.ts +108 -0
- package/lib/chart.component.d.ts +369 -0
- package/lib/chart.service.d.ts +222 -0
- package/lib/checkpoint.component.d.ts +51 -0
- package/lib/combobox.component.d.ts +90 -0
- package/lib/command-dialog.component.d.ts +53 -0
- package/lib/command.component.d.ts +189 -0
- package/lib/command.service.d.ts +67 -0
- package/lib/confirmation.component.d.ts +70 -0
- package/lib/context-menu-trigger.directive.d.ts +12 -0
- package/lib/context-menu.component.d.ts +41 -0
- package/lib/context-menu.service.d.ts +38 -0
- package/lib/context.component.d.ts +134 -0
- package/lib/conversation.component.d.ts +165 -0
- package/lib/data-table.component.d.ts +27 -1
- package/lib/date-picker.component.d.ts +72 -11
- package/lib/date-range-picker.component.d.ts +63 -6
- package/lib/date-time-picker.component.d.ts +119 -0
- package/lib/direction.component.d.ts +45 -0
- package/lib/field.component.d.ts +201 -0
- package/lib/inline-citation.component.d.ts +103 -0
- package/lib/input-group.component.d.ts +150 -0
- package/lib/item.component.d.ts +154 -0
- package/lib/kbd.component.d.ts +50 -0
- package/lib/marker.component.d.ts +58 -0
- package/lib/menubar.component.d.ts +247 -0
- package/lib/message-scroller.component.d.ts +159 -0
- package/lib/message-scroller.service.d.ts +73 -0
- package/lib/message.component.d.ts +128 -0
- package/lib/model-selector.component.d.ts +103 -0
- package/lib/multi-select.component.d.ts +66 -14
- package/lib/native-select.component.d.ts +57 -0
- package/lib/navigation-menu.component.d.ts +230 -0
- package/lib/plan.component.d.ts +120 -0
- package/lib/popover.component.d.ts +1 -0
- package/lib/prompt-input.component.d.ts +194 -0
- package/lib/queue.component.d.ts +106 -0
- package/lib/reasoning.component.d.ts +127 -0
- package/lib/resizable.component.d.ts +43 -0
- package/lib/segment.component.d.ts +13 -3
- package/lib/select.component.d.ts +37 -5
- package/lib/sheet.component.d.ts +3 -0
- package/lib/shimmer.component.d.ts +38 -0
- package/lib/sidebar.component.d.ts +2 -0
- package/lib/sources.component.d.ts +156 -0
- package/lib/spinner.component.d.ts +29 -0
- package/lib/suggestion.component.d.ts +96 -0
- package/lib/table.component.d.ts +106 -0
- package/lib/task.component.d.ts +151 -0
- package/lib/theme.service.d.ts +9 -0
- package/lib/time-picker.component.d.ts +243 -0
- package/lib/toast.service.d.ts +3 -1
- package/lib/toaster.component.d.ts +26 -9
- package/lib/tool.component.d.ts +158 -0
- package/lib/typography.component.d.ts +32 -0
- package/lib/utils/color.d.ts +19 -5
- package/package.json +1 -1
- package/public-api.d.ts +50 -0
- package/registry/docs-content.json +8497 -1553
- package/registry/llms-full.txt +2679 -318
- package/registry/llms.txt +43 -4
- package/registry/manifest.json +9093 -1739
- package/registry/r/accordion-item.json +1 -1
- package/registry/r/accordion.json +1 -1
- package/registry/r/alert-dialog-dynamic.json +1 -1
- package/registry/r/alert-dialog.json +1 -1
- package/registry/r/alert.json +1 -1
- package/registry/r/attachment.json +23 -0
- package/registry/r/avatar-fallback.json +1 -1
- package/registry/r/avatar.json +1 -1
- package/registry/r/badge.json +1 -1
- package/registry/r/breadcrumb-item.json +1 -1
- package/registry/r/breadcrumb-link.json +1 -1
- package/registry/r/breadcrumb-separator.json +1 -1
- package/registry/r/breadcrumb.json +1 -1
- package/registry/r/bubble.json +23 -0
- package/registry/r/button.json +1 -1
- package/registry/r/calendar.json +1 -1
- package/registry/r/card.json +1 -1
- package/registry/r/carousel.json +1 -1
- package/registry/r/chain-of-thought.json +23 -0
- package/registry/r/chart-pie.json +30 -0
- package/registry/r/chart.json +28 -0
- package/registry/r/checkbox.json +1 -1
- package/registry/r/checkpoint.json +23 -0
- package/registry/r/collapsible.json +1 -1
- package/registry/r/combobox.json +31 -0
- package/registry/r/command-dialog.json +21 -0
- package/registry/r/command.json +26 -0
- package/registry/r/confirmation.json +23 -0
- package/registry/r/context.json +26 -0
- package/registry/r/conversation.json +23 -0
- package/registry/r/country-selector.json +1 -1
- package/registry/r/data-table.json +1 -1
- package/registry/r/date-picker.json +4 -4
- package/registry/r/date-range-picker.json +3 -3
- package/registry/r/date-time-picker.json +28 -0
- package/registry/r/direction.json +16 -0
- package/registry/r/dropdown-item.json +1 -1
- package/registry/r/dropdown-label.json +1 -1
- package/registry/r/dropdown-menu.json +1 -1
- package/registry/r/dropdown-separator.json +1 -1
- package/registry/r/dropdown-trigger.json +1 -1
- package/registry/r/empty-state.json +1 -1
- package/registry/r/field.json +23 -0
- package/registry/r/hover-card.json +1 -1
- package/registry/r/inline-citation.json +26 -0
- package/registry/r/input-group.json +23 -0
- package/registry/r/input.json +1 -1
- package/registry/r/item.json +23 -0
- package/registry/r/kbd.json +23 -0
- package/registry/r/label.json +1 -1
- package/registry/r/marker.json +23 -0
- package/registry/r/masked-input.json +1 -1
- package/registry/r/menubar.json +24 -0
- package/registry/r/message-scroller.json +26 -0
- package/registry/r/message.json +23 -0
- package/registry/r/model-selector.json +32 -0
- package/registry/r/multi-select.json +2 -2
- package/registry/r/native-select.json +23 -0
- package/registry/r/navigation-menu.json +24 -0
- package/registry/r/otp-group.json +1 -1
- package/registry/r/otp-slot.json +1 -1
- package/registry/r/otp.json +1 -1
- package/registry/r/pagination.json +3 -2
- package/registry/r/plan.json +23 -0
- package/registry/r/popover-content.json +1 -1
- package/registry/r/popover.json +1 -1
- package/registry/r/progress.json +1 -1
- package/registry/r/prompt-input.json +23 -0
- package/registry/r/queue.json +23 -0
- package/registry/r/radio-group.json +1 -1
- package/registry/r/radio-item.json +1 -1
- package/registry/r/range-calendar.json +1 -1
- package/registry/r/reasoning.json +23 -0
- package/registry/r/segment.json +1 -1
- package/registry/r/select-group.json +1 -1
- package/registry/r/select-item.json +1 -1
- package/registry/r/select-separator.json +1 -1
- package/registry/r/select.json +4 -3
- package/registry/r/separator.json +1 -1
- package/registry/r/sheet.json +1 -1
- package/registry/r/shimmer.json +23 -0
- package/registry/r/sidebar.json +1 -1
- package/registry/r/skeleton.json +1 -1
- package/registry/r/sources.json +23 -0
- package/registry/r/spinner.json +23 -0
- package/registry/r/suggestion.json +23 -0
- package/registry/r/switch.json +1 -1
- package/registry/r/table.json +21 -0
- package/registry/r/tabs.json +1 -1
- package/registry/r/tag-input.json +1 -1
- package/registry/r/task.json +23 -0
- package/registry/r/textarea.json +1 -1
- package/registry/r/time-picker.json +24 -0
- package/registry/r/toaster.json +2 -2
- package/registry/r/toggle-group.json +1 -1
- package/registry/r/toggle.json +1 -1
- package/registry/r/tool.json +23 -0
- package/registry/r/typography.json +23 -0
- package/registry/registry.json +915 -22
- package/theme.css +109 -8
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
import { Component, ElementRef, HostListener, inject, ViewChild, ViewChildren, ChangeDetectorRef } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { ContextMenuService } from './context-menu.service';
|
|
4
|
+
import { cn } from './utils/cn';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
export class ContextMenuComponent {
|
|
7
|
+
contextMenuService = inject(ContextMenuService);
|
|
8
|
+
elementRef = inject(ElementRef);
|
|
9
|
+
cdr = inject(ChangeDetectorRef);
|
|
10
|
+
menuElement;
|
|
11
|
+
// We only have one active submenu now, so we can use ViewChild instead of ViewChildren
|
|
12
|
+
submenuElement;
|
|
13
|
+
itemButtons;
|
|
14
|
+
isOpen = false;
|
|
15
|
+
isPositioned = false;
|
|
16
|
+
isSubmenuPositioned = false;
|
|
17
|
+
items = [];
|
|
18
|
+
openSubmenuId = null;
|
|
19
|
+
activeSubmenuTrigger = null; // Store the button that triggered the submenu
|
|
20
|
+
activeIndex = -1;
|
|
21
|
+
stateSubscription;
|
|
22
|
+
submenuTimeout;
|
|
23
|
+
cn = cn;
|
|
24
|
+
ngOnInit() {
|
|
25
|
+
this.stateSubscription = this.contextMenuService.stateChanged.subscribe((state) => {
|
|
26
|
+
this.isOpen = state.isOpen;
|
|
27
|
+
this.items = state.items;
|
|
28
|
+
if (state.isOpen) {
|
|
29
|
+
this.activeIndex = -1;
|
|
30
|
+
this.isPositioned = false;
|
|
31
|
+
this.cdr.detectChanges();
|
|
32
|
+
requestAnimationFrame(() => {
|
|
33
|
+
this.positionMenu();
|
|
34
|
+
this.focusFirstItem();
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
this.closeSubmenu();
|
|
39
|
+
this.activeIndex = -1;
|
|
40
|
+
this.isPositioned = false;
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
// Helper to get items for the currently open submenu
|
|
45
|
+
get activeSubmenuItems() {
|
|
46
|
+
if (!this.openSubmenuId)
|
|
47
|
+
return [];
|
|
48
|
+
return this.items.find(i => i.id === this.openSubmenuId)?.submenu || [];
|
|
49
|
+
}
|
|
50
|
+
onDocumentEvents(event) {
|
|
51
|
+
if (!this.isOpen)
|
|
52
|
+
return;
|
|
53
|
+
// Check if click is inside main menu OR the active submenu
|
|
54
|
+
const clickedInsideMenu = this.menuElement?.nativeElement.contains(event.target);
|
|
55
|
+
const clickedInsideSubmenu = this.submenuElement?.nativeElement.contains(event.target);
|
|
56
|
+
if (clickedInsideMenu || clickedInsideSubmenu) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.contextMenuService.close();
|
|
60
|
+
}
|
|
61
|
+
async positionMenu() {
|
|
62
|
+
if (this.menuElement?.nativeElement) {
|
|
63
|
+
this.isPositioned = false;
|
|
64
|
+
this.cdr.detectChanges();
|
|
65
|
+
await this.contextMenuService.positionMenu(this.menuElement.nativeElement);
|
|
66
|
+
this.isPositioned = true;
|
|
67
|
+
this.cdr.detectChanges();
|
|
68
|
+
// Focus the menu container so Arrow/Enter/Escape keydown handlers fire.
|
|
69
|
+
this.menuElement.nativeElement.focus();
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
focusFirstItem() {
|
|
73
|
+
const firstEnabledIndex = this.items.findIndex(item => !item.disabled && !item.separator);
|
|
74
|
+
if (firstEnabledIndex !== -1) {
|
|
75
|
+
this.activeIndex = firstEnabledIndex;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
onItemClick(item) {
|
|
79
|
+
if (item.disabled || item.separator)
|
|
80
|
+
return;
|
|
81
|
+
if (item.submenu) {
|
|
82
|
+
// Toggle logic handled by enter/leave mostly, but click can force toggle
|
|
83
|
+
if (this.openSubmenuId === item.id) {
|
|
84
|
+
this.closeSubmenu();
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// We need the button ref to open it via click.
|
|
88
|
+
// Implementation detail: Hover is preferred for submenus.
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
this.contextMenuService.performAction(item.id);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
onItemMouseEnter(item, trigger) {
|
|
96
|
+
if (item.disabled || item.separator)
|
|
97
|
+
return;
|
|
98
|
+
// Clear any pending close actions
|
|
99
|
+
clearTimeout(this.submenuTimeout);
|
|
100
|
+
this.submenuTimeout = setTimeout(() => {
|
|
101
|
+
if (item.submenu) {
|
|
102
|
+
this.openSubmenuId = item.id;
|
|
103
|
+
this.activeSubmenuTrigger = trigger; // Save the trigger for positioning
|
|
104
|
+
this.positionSubmenu();
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
this.closeSubmenu();
|
|
108
|
+
}
|
|
109
|
+
}, 150);
|
|
110
|
+
}
|
|
111
|
+
onItemMouseLeave() {
|
|
112
|
+
// We don't close immediately; we wait to see if the user enters the submenu
|
|
113
|
+
// Logic handled by the timeout in `onItemMouseEnter` of a sibling,
|
|
114
|
+
// or we could add a timeout here to close if they go nowhere.
|
|
115
|
+
}
|
|
116
|
+
onSubmenuMouseEnter() {
|
|
117
|
+
// If user is hovering the submenu, keep it open
|
|
118
|
+
clearTimeout(this.submenuTimeout);
|
|
119
|
+
}
|
|
120
|
+
onSubmenuMouseLeave() {
|
|
121
|
+
// If user leaves submenu, standard behavior is usually to keep it open
|
|
122
|
+
// until they hover another main item or click away.
|
|
123
|
+
}
|
|
124
|
+
closeSubmenu() {
|
|
125
|
+
this.openSubmenuId = null;
|
|
126
|
+
this.activeSubmenuTrigger = null;
|
|
127
|
+
this.isSubmenuPositioned = false;
|
|
128
|
+
}
|
|
129
|
+
async positionSubmenu() {
|
|
130
|
+
this.isSubmenuPositioned = false;
|
|
131
|
+
this.cdr.detectChanges(); // Render the submenu DOM
|
|
132
|
+
requestAnimationFrame(async () => {
|
|
133
|
+
if (this.activeSubmenuTrigger && this.submenuElement) {
|
|
134
|
+
await this.contextMenuService.positionSubmenu(this.activeSubmenuTrigger, this.submenuElement.nativeElement);
|
|
135
|
+
this.isSubmenuPositioned = true;
|
|
136
|
+
this.cdr.detectChanges();
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
onSubItemClick(item) {
|
|
141
|
+
if (item.disabled || item.separator)
|
|
142
|
+
return;
|
|
143
|
+
this.contextMenuService.performAction(item.id);
|
|
144
|
+
}
|
|
145
|
+
onKeyDown(event) {
|
|
146
|
+
switch (event.key) {
|
|
147
|
+
case 'ArrowDown':
|
|
148
|
+
event.preventDefault();
|
|
149
|
+
this.navigate(1);
|
|
150
|
+
break;
|
|
151
|
+
case 'ArrowUp':
|
|
152
|
+
event.preventDefault();
|
|
153
|
+
this.navigate(-1);
|
|
154
|
+
break;
|
|
155
|
+
case 'ArrowRight':
|
|
156
|
+
const currentItem = this.items[this.activeIndex];
|
|
157
|
+
if (currentItem?.submenu) {
|
|
158
|
+
event.preventDefault();
|
|
159
|
+
// Force open submenu via keyboard
|
|
160
|
+
this.openSubmenuId = currentItem.id;
|
|
161
|
+
const trigger = this.itemButtons.toArray()[this.activeIndex]?.nativeElement;
|
|
162
|
+
if (trigger) {
|
|
163
|
+
this.activeSubmenuTrigger = trigger;
|
|
164
|
+
this.positionSubmenu();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
break;
|
|
168
|
+
case 'ArrowLeft':
|
|
169
|
+
if (this.openSubmenuId) {
|
|
170
|
+
event.preventDefault();
|
|
171
|
+
this.closeSubmenu();
|
|
172
|
+
}
|
|
173
|
+
break;
|
|
174
|
+
case 'Enter':
|
|
175
|
+
if (this.activeIndex !== -1) {
|
|
176
|
+
event.preventDefault();
|
|
177
|
+
this.onItemClick(this.items[this.activeIndex]);
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
case 'Escape':
|
|
181
|
+
event.preventDefault();
|
|
182
|
+
this.contextMenuService.close();
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
navigate(direction) {
|
|
187
|
+
let nextIndex = this.activeIndex + direction;
|
|
188
|
+
const count = this.items.length;
|
|
189
|
+
while (nextIndex >= 0 && nextIndex < count) {
|
|
190
|
+
const item = this.items[nextIndex];
|
|
191
|
+
if (!item.disabled && !item.separator) {
|
|
192
|
+
this.activeIndex = nextIndex;
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
nextIndex += direction;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
onEscape() {
|
|
199
|
+
this.contextMenuService.close();
|
|
200
|
+
}
|
|
201
|
+
ngOnDestroy() {
|
|
202
|
+
if (this.stateSubscription) {
|
|
203
|
+
this.stateSubscription.unsubscribe();
|
|
204
|
+
}
|
|
205
|
+
clearTimeout(this.submenuTimeout);
|
|
206
|
+
}
|
|
207
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContextMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
208
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ContextMenuComponent, isStandalone: true, selector: "tolle-context-menu", host: { listeners: { "document:click": "onDocumentEvents($event)", "document:contextmenu": "onDocumentEvents($event)", "document:keydown.escape": "onEscape()" } }, viewQueries: [{ propertyName: "menuElement", first: true, predicate: ["menu"], descendants: true }, { propertyName: "submenuElement", first: true, predicate: ["submenu"], descendants: true }, { propertyName: "itemButtons", predicate: ["itemButton"], descendants: true }], ngImport: i0, template: `
|
|
209
|
+
@if (isOpen) {
|
|
210
|
+
<div
|
|
211
|
+
#menu
|
|
212
|
+
role="menu"
|
|
213
|
+
aria-orientation="vertical"
|
|
214
|
+
tabindex="-1"
|
|
215
|
+
[attr.data-state]="isOpen ? 'open' : 'closed'"
|
|
216
|
+
class="fixed z-50 min-w-[12rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md
|
|
217
|
+
data-[state=closed]:animate-out data-[state=open]:animate-in
|
|
218
|
+
data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0
|
|
219
|
+
data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95
|
|
220
|
+
slide-in-from-top-2"
|
|
221
|
+
[style.visibility]="isPositioned ? 'visible' : 'hidden'"
|
|
222
|
+
[style.opacity]="isPositioned ? '1' : '0'"
|
|
223
|
+
style="will-change: transform; top: 0; left: 0;"
|
|
224
|
+
(keydown)="onKeyDown($event)"
|
|
225
|
+
>
|
|
226
|
+
<div class="flex flex-col">
|
|
227
|
+
@for (item of items; track $index) {
|
|
228
|
+
@if (item.separator) {
|
|
229
|
+
<div role="separator" class="h-px -mx-1 my-1 bg-border"></div>
|
|
230
|
+
} @else {
|
|
231
|
+
<div class="relative group">
|
|
232
|
+
<button
|
|
233
|
+
#itemButton
|
|
234
|
+
type="button"
|
|
235
|
+
role="menuitem"
|
|
236
|
+
[attr.aria-haspopup]="item.submenu ? 'true' : null"
|
|
237
|
+
[attr.aria-expanded]="openSubmenuId === item.id ? 'true' : null"
|
|
238
|
+
[attr.aria-disabled]="item.disabled ? 'true' : null"
|
|
239
|
+
(click)="onItemClick(item)"
|
|
240
|
+
(mouseenter)="onItemMouseEnter(item, itemButton)"
|
|
241
|
+
(mouseleave)="onItemMouseLeave()"
|
|
242
|
+
[disabled]="item.disabled"
|
|
243
|
+
[class]="cn(
|
|
244
|
+
'relative flex w-full cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
|
|
245
|
+
'transition-colors focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground',
|
|
246
|
+
'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
|
247
|
+
item.destructive ? 'text-destructive focus:bg-destructive/10 focus:text-destructive' : '',
|
|
248
|
+
item.disabled && 'opacity-50 cursor-not-allowed pointer-events-none',
|
|
249
|
+
(item.type === 'checkbox' || item.type === 'radio') ? 'pl-8' : '',
|
|
250
|
+
activeIndex === $index && 'bg-accent text-accent-foreground'
|
|
251
|
+
)"
|
|
252
|
+
>
|
|
253
|
+
@if (item.checked) {
|
|
254
|
+
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
255
|
+
<i [class]="item.type === 'radio' ? 'ri-checkbox-blank-circle-fill h-2 w-2 fill-current' : 'ri-check-line h-4 w-4'"></i>
|
|
256
|
+
</span>
|
|
257
|
+
}
|
|
258
|
+
@if (item.icon) {
|
|
259
|
+
<i [class]="cn(item.icon, 'mr-2 h-4 w-4')"></i>
|
|
260
|
+
}
|
|
261
|
+
<span class="flex-1 text-left">{{ item.label }}</span>
|
|
262
|
+
@if (item.shortcut && !item.submenu) {
|
|
263
|
+
<span class="ml-auto text-xs tracking-widest text-muted-foreground pl-2">{{ item.shortcut }}</span>
|
|
264
|
+
}
|
|
265
|
+
@if (item.submenu) {
|
|
266
|
+
<i class="ri-arrow-right-s-line ml-auto h-4 w-4 opacity-50"></i>
|
|
267
|
+
}
|
|
268
|
+
</button>
|
|
269
|
+
</div>
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
|
|
275
|
+
@if (openSubmenuId && activeSubmenuItems.length > 0) {
|
|
276
|
+
<div
|
|
277
|
+
#submenu
|
|
278
|
+
role="menu"
|
|
279
|
+
[id]="'submenu-' + openSubmenuId"
|
|
280
|
+
class="fixed z-50 min-w-[12rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md"
|
|
281
|
+
[style.visibility]="isSubmenuPositioned ? 'visible' : 'hidden'"
|
|
282
|
+
[style.opacity]="isSubmenuPositioned ? '1' : '0'"
|
|
283
|
+
style="will-change: transform"
|
|
284
|
+
(mouseenter)="onSubmenuMouseEnter()"
|
|
285
|
+
(mouseleave)="onSubmenuMouseLeave()"
|
|
286
|
+
>
|
|
287
|
+
@for (subItem of activeSubmenuItems; track $index) {
|
|
288
|
+
@if (subItem.separator) {
|
|
289
|
+
<div role="separator" class="h-px -mx-1 my-1 bg-border"></div>
|
|
290
|
+
} @else {
|
|
291
|
+
<button
|
|
292
|
+
type="button"
|
|
293
|
+
role="menuitem"
|
|
294
|
+
(click)="onSubItemClick(subItem)"
|
|
295
|
+
[disabled]="subItem.disabled"
|
|
296
|
+
[class]="cn(
|
|
297
|
+
'relative flex w-full cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
|
|
298
|
+
'transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground',
|
|
299
|
+
subItem.disabled && 'opacity-50 cursor-not-allowed pointer-events-none',
|
|
300
|
+
(subItem.type === 'checkbox' || subItem.type === 'radio') ? 'pl-8' : '',
|
|
301
|
+
subItem.destructive ? 'text-destructive hover:bg-destructive/10' : ''
|
|
302
|
+
)"
|
|
303
|
+
>
|
|
304
|
+
@if (subItem.checked) {
|
|
305
|
+
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
306
|
+
<i [class]="subItem.type === 'radio' ? 'ri-checkbox-blank-circle-fill h-2 w-2 fill-current' : 'ri-check-line h-4 w-4'"></i>
|
|
307
|
+
</span>
|
|
308
|
+
}
|
|
309
|
+
@if (subItem.icon) {
|
|
310
|
+
<i [class]="cn(subItem.icon, 'mr-2 h-4 w-4')"></i>
|
|
311
|
+
}
|
|
312
|
+
<span class="flex-1 text-left">{{ subItem.label }}</span>
|
|
313
|
+
@if (subItem.shortcut) {
|
|
314
|
+
<span class="ml-auto text-xs tracking-widest text-muted-foreground pl-2">{{ subItem.shortcut }}</span>
|
|
315
|
+
}
|
|
316
|
+
</button>
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
</div>
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
`, isInline: true, styles: [":host{display:contents}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
323
|
+
}
|
|
324
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContextMenuComponent, decorators: [{
|
|
325
|
+
type: Component,
|
|
326
|
+
args: [{ selector: 'tolle-context-menu', standalone: true, imports: [CommonModule], template: `
|
|
327
|
+
@if (isOpen) {
|
|
328
|
+
<div
|
|
329
|
+
#menu
|
|
330
|
+
role="menu"
|
|
331
|
+
aria-orientation="vertical"
|
|
332
|
+
tabindex="-1"
|
|
333
|
+
[attr.data-state]="isOpen ? 'open' : 'closed'"
|
|
334
|
+
class="fixed z-50 min-w-[12rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md
|
|
335
|
+
data-[state=closed]:animate-out data-[state=open]:animate-in
|
|
336
|
+
data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0
|
|
337
|
+
data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95
|
|
338
|
+
slide-in-from-top-2"
|
|
339
|
+
[style.visibility]="isPositioned ? 'visible' : 'hidden'"
|
|
340
|
+
[style.opacity]="isPositioned ? '1' : '0'"
|
|
341
|
+
style="will-change: transform; top: 0; left: 0;"
|
|
342
|
+
(keydown)="onKeyDown($event)"
|
|
343
|
+
>
|
|
344
|
+
<div class="flex flex-col">
|
|
345
|
+
@for (item of items; track $index) {
|
|
346
|
+
@if (item.separator) {
|
|
347
|
+
<div role="separator" class="h-px -mx-1 my-1 bg-border"></div>
|
|
348
|
+
} @else {
|
|
349
|
+
<div class="relative group">
|
|
350
|
+
<button
|
|
351
|
+
#itemButton
|
|
352
|
+
type="button"
|
|
353
|
+
role="menuitem"
|
|
354
|
+
[attr.aria-haspopup]="item.submenu ? 'true' : null"
|
|
355
|
+
[attr.aria-expanded]="openSubmenuId === item.id ? 'true' : null"
|
|
356
|
+
[attr.aria-disabled]="item.disabled ? 'true' : null"
|
|
357
|
+
(click)="onItemClick(item)"
|
|
358
|
+
(mouseenter)="onItemMouseEnter(item, itemButton)"
|
|
359
|
+
(mouseleave)="onItemMouseLeave()"
|
|
360
|
+
[disabled]="item.disabled"
|
|
361
|
+
[class]="cn(
|
|
362
|
+
'relative flex w-full cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
|
|
363
|
+
'transition-colors focus:bg-accent focus:text-accent-foreground hover:bg-accent hover:text-accent-foreground',
|
|
364
|
+
'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
|
365
|
+
item.destructive ? 'text-destructive focus:bg-destructive/10 focus:text-destructive' : '',
|
|
366
|
+
item.disabled && 'opacity-50 cursor-not-allowed pointer-events-none',
|
|
367
|
+
(item.type === 'checkbox' || item.type === 'radio') ? 'pl-8' : '',
|
|
368
|
+
activeIndex === $index && 'bg-accent text-accent-foreground'
|
|
369
|
+
)"
|
|
370
|
+
>
|
|
371
|
+
@if (item.checked) {
|
|
372
|
+
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
373
|
+
<i [class]="item.type === 'radio' ? 'ri-checkbox-blank-circle-fill h-2 w-2 fill-current' : 'ri-check-line h-4 w-4'"></i>
|
|
374
|
+
</span>
|
|
375
|
+
}
|
|
376
|
+
@if (item.icon) {
|
|
377
|
+
<i [class]="cn(item.icon, 'mr-2 h-4 w-4')"></i>
|
|
378
|
+
}
|
|
379
|
+
<span class="flex-1 text-left">{{ item.label }}</span>
|
|
380
|
+
@if (item.shortcut && !item.submenu) {
|
|
381
|
+
<span class="ml-auto text-xs tracking-widest text-muted-foreground pl-2">{{ item.shortcut }}</span>
|
|
382
|
+
}
|
|
383
|
+
@if (item.submenu) {
|
|
384
|
+
<i class="ri-arrow-right-s-line ml-auto h-4 w-4 opacity-50"></i>
|
|
385
|
+
}
|
|
386
|
+
</button>
|
|
387
|
+
</div>
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
</div>
|
|
391
|
+
</div>
|
|
392
|
+
|
|
393
|
+
@if (openSubmenuId && activeSubmenuItems.length > 0) {
|
|
394
|
+
<div
|
|
395
|
+
#submenu
|
|
396
|
+
role="menu"
|
|
397
|
+
[id]="'submenu-' + openSubmenuId"
|
|
398
|
+
class="fixed z-50 min-w-[12rem] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md"
|
|
399
|
+
[style.visibility]="isSubmenuPositioned ? 'visible' : 'hidden'"
|
|
400
|
+
[style.opacity]="isSubmenuPositioned ? '1' : '0'"
|
|
401
|
+
style="will-change: transform"
|
|
402
|
+
(mouseenter)="onSubmenuMouseEnter()"
|
|
403
|
+
(mouseleave)="onSubmenuMouseLeave()"
|
|
404
|
+
>
|
|
405
|
+
@for (subItem of activeSubmenuItems; track $index) {
|
|
406
|
+
@if (subItem.separator) {
|
|
407
|
+
<div role="separator" class="h-px -mx-1 my-1 bg-border"></div>
|
|
408
|
+
} @else {
|
|
409
|
+
<button
|
|
410
|
+
type="button"
|
|
411
|
+
role="menuitem"
|
|
412
|
+
(click)="onSubItemClick(subItem)"
|
|
413
|
+
[disabled]="subItem.disabled"
|
|
414
|
+
[class]="cn(
|
|
415
|
+
'relative flex w-full cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none',
|
|
416
|
+
'transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground',
|
|
417
|
+
subItem.disabled && 'opacity-50 cursor-not-allowed pointer-events-none',
|
|
418
|
+
(subItem.type === 'checkbox' || subItem.type === 'radio') ? 'pl-8' : '',
|
|
419
|
+
subItem.destructive ? 'text-destructive hover:bg-destructive/10' : ''
|
|
420
|
+
)"
|
|
421
|
+
>
|
|
422
|
+
@if (subItem.checked) {
|
|
423
|
+
<span class="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
424
|
+
<i [class]="subItem.type === 'radio' ? 'ri-checkbox-blank-circle-fill h-2 w-2 fill-current' : 'ri-check-line h-4 w-4'"></i>
|
|
425
|
+
</span>
|
|
426
|
+
}
|
|
427
|
+
@if (subItem.icon) {
|
|
428
|
+
<i [class]="cn(subItem.icon, 'mr-2 h-4 w-4')"></i>
|
|
429
|
+
}
|
|
430
|
+
<span class="flex-1 text-left">{{ subItem.label }}</span>
|
|
431
|
+
@if (subItem.shortcut) {
|
|
432
|
+
<span class="ml-auto text-xs tracking-widest text-muted-foreground pl-2">{{ subItem.shortcut }}</span>
|
|
433
|
+
}
|
|
434
|
+
</button>
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
</div>
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
`, styles: [":host{display:contents}\n"] }]
|
|
441
|
+
}], propDecorators: { menuElement: [{
|
|
442
|
+
type: ViewChild,
|
|
443
|
+
args: ['menu']
|
|
444
|
+
}], submenuElement: [{
|
|
445
|
+
type: ViewChild,
|
|
446
|
+
args: ['submenu']
|
|
447
|
+
}], itemButtons: [{
|
|
448
|
+
type: ViewChildren,
|
|
449
|
+
args: ['itemButton']
|
|
450
|
+
}], onDocumentEvents: [{
|
|
451
|
+
type: HostListener,
|
|
452
|
+
args: ['document:click', ['$event']]
|
|
453
|
+
}, {
|
|
454
|
+
type: HostListener,
|
|
455
|
+
args: ['document:contextmenu', ['$event']]
|
|
456
|
+
}], onEscape: [{
|
|
457
|
+
type: HostListener,
|
|
458
|
+
args: ['document:keydown.escape']
|
|
459
|
+
}] } });
|
|
460
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC1tZW51LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RvbGxlL3NyYy9saWIvY29udGV4dC1tZW51LmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFxQixTQUFTLEVBQUUsWUFBWSxFQUFhLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3RKLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQW1CLGtCQUFrQixFQUFvQixNQUFNLHdCQUF3QixDQUFDO0FBQy9GLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxZQUFZLENBQUM7O0FBNkhoQyxNQUFNLE9BQU8sb0JBQW9CO0lBQ3ZCLGtCQUFrQixHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ2hELFVBQVUsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDaEMsR0FBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0lBRXJCLFdBQVcsQ0FBOEI7SUFFNUQsdUZBQXVGO0lBQ2pFLGNBQWMsQ0FBOEI7SUFFdEMsV0FBVyxDQUE0QztJQUVuRixNQUFNLEdBQUcsS0FBSyxDQUFDO0lBQ2YsWUFBWSxHQUFHLEtBQUssQ0FBQztJQUNyQixtQkFBbUIsR0FBRyxLQUFLLENBQUM7SUFDNUIsS0FBSyxHQUFzQixFQUFFLENBQUM7SUFFOUIsYUFBYSxHQUFrQixJQUFJLENBQUM7SUFDcEMsb0JBQW9CLEdBQXVCLElBQUksQ0FBQyxDQUFDLDhDQUE4QztJQUUvRixXQUFXLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDVCxpQkFBaUIsQ0FBTTtJQUN2QixjQUFjLENBQU07SUFFVCxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBRTNCLFFBQVE7UUFDTixJQUFJLENB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Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0hULGtHQW5IUyxZQUFZOzs0RkF3SFgsb0JBQW9CO2tCQTNIaEMsU0FBUzsrQkFDRSxvQkFBb0IsY0FDbEIsSUFBSSxXQUNQLENBQUMsWUFBWSxDQUFDLFlBQ2I7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtIVDs4QkFVa0IsV0FBVztzQkFBN0IsU0FBUzt1QkFBQyxNQUFNO2dCQUdLLGNBQWM7c0JBQW5DLFNBQVM7dUJBQUMsU0FBUztnQkFFUSxXQUFXO3NCQUF0QyxZQUFZO3VCQUFDLFlBQVk7Z0JBNkMxQixnQkFBZ0I7c0JBRmYsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsQ0FBQzs7c0JBQ3pDLFlBQVk7dUJBQUMsc0JBQXNCLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBc0toRCxRQUFRO3NCQURQLFlBQVk7dUJBQUMseUJBQXlCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBIb3N0TGlzdGVuZXIsIGluamVjdCwgT25EZXN0cm95LCBPbkluaXQsIFZpZXdDaGlsZCwgVmlld0NoaWxkcmVuLCBRdWVyeUxpc3QsIENoYW5nZURldGVjdG9yUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgQ29udGV4dE1lbnVJdGVtLCBDb250ZXh0TWVudVNlcnZpY2UsIENvbnRleHRNZW51U3RhdGUgfSBmcm9tICcuL2NvbnRleHQtbWVudS5zZXJ2aWNlJztcbmltcG9ydCB7IGNuIH0gZnJvbSAnLi91dGlscy9jbic7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3RvbGxlLWNvbnRleHQtbWVudScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxuICB0ZW1wbGF0ZTogYFxuICAgIEBpZiAoaXNPcGVuKSB7XG4gICAgICA8ZGl2XG4gICAgICAgICNtZW51XG4gICAgICAgIHJvbGU9XCJtZW51XCJcbiAgICAgICAgYXJpYS1vcmllbnRhdGlvbj1cInZlcnRpY2FsXCJcbiAgICAgICAgdGFiaW5kZXg9XCItMVwiXG4gICAgICAgIFthdHRyLmRhdGEtc3RhdGVdPVwiaXNPcGVuID8gJ29wZW4nIDogJ2Nsb3NlZCdcIlxuICAgICAgICBjbGFzcz1cImZpeGVkIHotNTAgbWluLXctWzEycmVtXSBvdmVyZmxvdy1oaWRkZW4gcm91bmRlZC1tZCBib3JkZXIgYm9yZGVyLWJvcmRlciBiZy1wb3BvdmVyIHAtMSB0ZXh0LXBvcG92ZXItZm9yZWdyb3VuZCBzaGFkb3ctbWRcbiAgICAgICAgICAgICAgIGRhdGEtW3N0YXRlPWNsb3NlZF06YW5pbWF0ZS1vdXQgZGF0YS1bc3RhdGU9b3Blbl06YW5pbWF0ZS1pblxuICAgICAgICAgICAgICAgZGF0YS1bc3RhdGU9Y2xvc2VkXTpmYWRlLW91dC0wIGRhdGEtW3N0YXRlPW9wZW5dOmZhZGUtaW4tMFxuICAgICAgICAgICAgICAgZGF0YS1bc3RhdGU9Y2xvc2VkXTp6b29tLW91dC05NSBkYXRhLVtzdGF0ZT1vcGVuXTp6b29tLWluLTk1XG4gICAgICAgICAgICAgICBzbGlkZS1pbi1mcm9tLXRvcC0yXCJcbiAgICAgICAgW3N0eWxlLnZpc2liaWxpdHldPVwiaXNQb3NpdGlvbmVkID8gJ3Zpc2libGUnIDogJ2hpZGRlbidcIlxuICAgICAgICBbc3R5bGUub3BhY2l0eV09XCJpc1Bvc2l0aW9uZWQgPyAnMScgOiAnMCdcIlxuICAgICAgICBzdHlsZT1cIndpbGwtY2hhbmdlOiB0cmFuc2Zvcm07IHRvcDogMDsgbGVmdDogMDtcIlxuICAgICAgICAoa2V5ZG93bik9XCJvbktleURvd24oJGV2ZW50KVwiXG4gICAgICA+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtY29sXCI+XG4gICAgICAgICAgQGZvciAoaXRlbSBvZiBpdGVtczsgdHJhY2sgJGluZGV4KSB7XG4gICAgICAgICAgICBAaWYgKGl0ZW0uc2VwYXJhdG9yKSB7XG4gICAgICAgICAgICAgIDxkaXYgcm9sZT1cInNlcGFyYXRvclwiIGNsYXNzPVwiaC1weCAtbXgtMSBteS0xIGJnLWJvcmRlclwiPjwvZGl2PlxuICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyZWxhdGl2ZSBncm91cFwiPlxuICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICNpdGVtQnV0dG9uXG4gICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgIHJvbGU9XCJtZW51aXRlbVwiXG4gICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWhhc3BvcHVwXT1cIml0ZW0uc3VibWVudSA/ICd0cnVlJyA6IG51bGxcIlxuICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1leHBhbmRlZF09XCJvcGVuU3VibWVudUlkID09PSBpdGVtLmlkID8gJ3RydWUnIDogbnVsbFwiXG4gICAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWRpc2FibGVkXT1cIml0ZW0uZGlzYWJsZWQgPyAndHJ1ZScgOiBudWxsXCJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkl0ZW1DbGljayhpdGVtKVwiXG4gICAgICAgICAgICAgICAgICAobW91c2VlbnRlcik9XCJvbkl0ZW1Nb3VzZUVudGVyKGl0ZW0sIGl0ZW1CdXR0b24pXCJcbiAgICAgICAgICAgICAgICAgIChtb3VzZWxlYXZlKT1cIm9uSXRlbU1vdXNlTGVhdmUoKVwiXG4gICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaXRlbS5kaXNhYmxlZFwiXG4gICAgICAgICAgICAgICAgICBbY2xhc3NdPVwiY24oXG4gICAgICAgICAgICAgICAgICAgICdyZWxhdGl2ZSBmbGV4IHctZnVsbCBjdXJzb3ItZGVmYXVsdCBzZWxlY3Qtbm9uZSBpdGVtcy1jZW50ZXIgcm91bmRlZC1zbSBweC0yIHB5LTEuNSB0ZXh0LXNtIG91dGxpbmUtbm9uZScsXG4gICAgICAgICAgICAgICAgICAgICd0cmFuc2l0aW9uLWNvbG9ycyBmb2N1czpiZy1hY2NlbnQgZm9jdXM6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCBob3ZlcjpiZy1hY2NlbnQgaG92ZXI6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCcsXG4gICAgICAgICAgICAgICAgICAgICdkYXRhLVtkaXNhYmxlZF06cG9pbnRlci1ldmVudHMtbm9uZSBkYXRhLVtkaXNhYmxlZF06b3BhY2l0eS01MCcsXG4gICAgICAgICAgICAgICAgICAgIGl0ZW0uZGVzdHJ1Y3RpdmUgPyAndGV4dC1kZXN0cnVjdGl2ZSBmb2N1czpiZy1kZXN0cnVjdGl2ZS8xMCBmb2N1czp0ZXh0LWRlc3RydWN0aXZlJyA6ICcnLFxuICAgICAgICAgICAgICAgICAgICBpdGVtLmRpc2FibGVkICYmICdvcGFjaXR5LTUwIGN1cnNvci1ub3QtYWxsb3dlZCBwb2ludGVyLWV2ZW50cy1ub25lJyxcbiAgICAgICAgICAgICAgICAgICAgKGl0ZW0udHlwZSA9PT0gJ2NoZWNrYm94JyB8fCBpdGVtLnR5cGUgPT09ICdyYWRpbycpID8gJ3BsLTgnIDogJycsXG4gICAgICAgICAgICAgICAgICAgIGFjdGl2ZUluZGV4ID09PSAkaW5kZXggJiYgJ2JnLWFjY2VudCB0ZXh0LWFjY2VudC1mb3JlZ3JvdW5kJ1xuICAgICAgICAgICAgICAgICAgKVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgQGlmIChpdGVtLmNoZWNrZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJhYnNvbHV0ZSBsZWZ0LTIgZmxleCBoLTMuNSB3LTMuNSBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8aSBbY2xhc3NdPVwiaXRlbS50eXBlID09PSAncmFkaW8nID8gJ3JpLWNoZWNrYm94LWJsYW5rLWNpcmNsZS1maWxsIGgtMiB3LTIgZmlsbC1jdXJyZW50JyA6ICdyaS1jaGVjay1saW5lIGgtNCB3LTQnXCI+PC9pPlxuICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBAaWYgKGl0ZW0uaWNvbikge1xuICAgICAgICAgICAgICAgICAgICA8aSBbY2xhc3NdPVwiY24oaXRlbS5pY29uLCAnbXItMiBoLTQgdy00JylcIj48L2k+XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImZsZXgtMSB0ZXh0LWxlZnRcIj57eyBpdGVtLmxhYmVsIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgQGlmIChpdGVtLnNob3J0Y3V0ICYmICFpdGVtLnN1Ym1lbnUpIHtcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJtbC1hdXRvIHRleHQteHMgdHJhY2tpbmctd2lkZXN0IHRleHQtbXV0ZWQtZm9yZWdyb3VuZCBwbC0yXCI+e3sgaXRlbS5zaG9ydGN1dCB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIEBpZiAoaXRlbS5zdWJtZW51KSB7XG4gICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwicmktYXJyb3ctcmlnaHQtcy1saW5lIG1sLWF1dG8gaC00IHctNCBvcGFjaXR5LTUwXCI+PC9pPlxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIEBpZiAob3BlblN1Ym1lbnVJZCAmJiBhY3RpdmVTdWJtZW51SXRlbXMubGVuZ3RoID4gMCkge1xuICAgICAgICA8ZGl2XG4gICAgICAgICAgI3N1Ym1lbnVcbiAgICAgICAgICByb2xlPVwibWVudVwiXG4gICAgICAgICAgW2lkXT1cIidzdWJtZW51LScgKyBvcGVuU3VibWVudUlkXCJcbiAgICAgICAgICBjbGFzcz1cImZpeGVkIHotNTAgbWluLXctWzEycmVtXSBvdmVyZmxvdy1oaWRkZW4gcm91bmRlZC1tZCBib3JkZXIgYm9yZGVyLWJvcmRlciBiZy1wb3BvdmVyIHAtMSB0ZXh0LXBvcG92ZXItZm9yZWdyb3VuZCBzaGFkb3ctbWRcIlxuICAgICAgICAgIFtzdHlsZS52aXNpYmlsaXR5XT1cImlzU3VibWVudVBvc2l0aW9uZWQgPyAndmlzaWJsZScgOiAnaGlkZGVuJ1wiXG4gICAgICAgICAgW3N0eWxlLm9wYWNpdHldPVwiaXNTdWJtZW51UG9zaXRpb25lZCA/ICcxJyA6ICcwJ1wiXG4gICAgICAgICAgc3R5bGU9XCJ3aWxsLWNoYW5nZTogdHJhbnNmb3JtXCJcbiAgICAgICAgICAobW91c2VlbnRlcik9XCJvblN1Ym1lbnVNb3VzZUVudGVyKClcIlxuICAgICAgICAgIChtb3VzZWxlYXZlKT1cIm9uU3VibWVudU1vdXNlTGVhdmUoKVwiXG4gICAgICAgID5cbiAgICAgICAgICBAZm9yIChzdWJJdGVtIG9mIGFjdGl2ZVN1Ym1lbnVJdGVtczsgdHJhY2sgJGluZGV4KSB7XG4gICAgICAgICAgICBAaWYgKHN1Ykl0ZW0uc2VwYXJhdG9yKSB7XG4gICAgICAgICAgICAgIDxkaXYgcm9sZT1cInNlcGFyYXRvclwiIGNsYXNzPVwiaC1weCAtbXgtMSBteS0xIGJnLWJvcmRlclwiPjwvZGl2PlxuICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICByb2xlPVwibWVudWl0ZW1cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJvblN1Ykl0ZW1DbGljayhzdWJJdGVtKVwiXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cInN1Ykl0ZW0uZGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgIFtjbGFzc109XCJjbihcbiAgICAgICAgICAgICAgICAgICdyZWxhdGl2ZSBmbGV4IHctZnVsbCBjdXJzb3ItZGVmYXVsdCBzZWxlY3Qtbm9uZSBpdGVtcy1jZW50ZXIgcm91bmRlZC1zbSBweC0yIHB5LTEuNSB0ZXh0LXNtIG91dGxpbmUtbm9uZScsXG4gICAgICAgICAgICAgICAgICAndHJhbnNpdGlvbi1jb2xvcnMgaG92ZXI6YmctYWNjZW50IGhvdmVyOnRleHQtYWNjZW50LWZvcmVncm91bmQgZm9jdXM6YmctYWNjZW50IGZvY3VzOnRleHQtYWNjZW50LWZvcmVncm91bmQnLFxuICAgICAgICAgICAgICAgICAgc3ViSXRlbS5kaXNhYmxlZCAmJiAnb3BhY2l0eS01MCBjdXJzb3Itbm90LWFsbG93ZWQgcG9pbnRlci1ldmVudHMtbm9uZScsXG4gICAgICAgICAgICAgICAgICAoc3ViSXRlbS50eXBlID09PSAnY2hlY2tib3gnIHx8IHN1Ykl0ZW0udHlwZSA9PT0gJ3JhZGlvJykgPyAncGwtOCcgOiAnJyxcbiAgICAgICAgICAgICAgICAgIHN1Ykl0ZW0uZGVzdHJ1Y3RpdmUgPyAndGV4dC1kZXN0cnVjdGl2ZSBob3ZlcjpiZy1kZXN0cnVjdGl2ZS8xMCcgOiAnJ1xuICAgICAgICAgICAgICAgIClcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgQGlmIChzdWJJdGVtLmNoZWNrZWQpIHtcbiAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWJzb2x1dGUgbGVmdC0yIGZsZXggaC0zLjUgdy0zLjUgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgICAgIDxpIFtjbGFzc109XCJzdWJJdGVtLnR5cGUgPT09ICdyYWRpbycgPyAncmktY2hlY2tib3gtYmxhbmstY2lyY2xlLWZpbGwgaC0yIHctMiBmaWxsLWN1cnJlbnQnIDogJ3JpLWNoZWNrLWxpbmUgaC00IHctNCdcIj48L2k+XG4gICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIEBpZiAoc3ViSXRlbS5pY29uKSB7XG4gICAgICAgICAgICAgICAgICA8aSBbY2xhc3NdPVwiY24oc3ViSXRlbS5pY29uLCAnbXItMiBoLTQgdy00JylcIj48L2k+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZmxleC0xIHRleHQtbGVmdFwiPnt7IHN1Ykl0ZW0ubGFiZWwgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgQGlmIChzdWJJdGVtLnNob3J0Y3V0KSB7XG4gICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm1sLWF1dG8gdGV4dC14cyB0cmFja2luZy13aWRlc3QgdGV4dC1tdXRlZC1mb3JlZ3JvdW5kIHBsLTJcIj57eyBzdWJJdGVtLnNob3J0Y3V0IH19PC9zcGFuPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cbiAgICB9XG4gIGAsXG4gIHN0eWxlczogW2BcbiAgICA6aG9zdCB7IGRpc3BsYXk6IGNvbnRlbnRzOyB9XG4gIGBdXG59KVxuZXhwb3J0IGNsYXNzIENvbnRleHRNZW51Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICBwcml2YXRlIGNvbnRleHRNZW51U2VydmljZSA9IGluamVjdChDb250ZXh0TWVudVNlcnZpY2UpO1xuICBwcml2YXRlIGVsZW1lbnRSZWYgPSBpbmplY3QoRWxlbWVudFJlZik7XG4gIHByaXZhdGUgY2RyID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcblxuICBAVmlld0NoaWxkKCdtZW51JykgbWVudUVsZW1lbnQhOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PjtcblxuICAvLyBXZSBvbmx5IGhhdmUgb25lIGFjdGl2ZSBzdWJtZW51IG5vdywgc28gd2UgY2FuIHVzZSBWaWV3Q2hpbGQgaW5zdGVhZCBvZiBWaWV3Q2hpbGRyZW5cbiAgQFZpZXdDaGlsZCgnc3VibWVudScpIHN1Ym1lbnVFbGVtZW50ITogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD47XG5cbiAgQFZpZXdDaGlsZHJlbignaXRlbUJ1dHRvbicpIGl0ZW1CdXR0b25zITogUXVlcnlMaXN0PEVsZW1lbnRSZWY8SFRNTEJ1dHRvbkVsZW1lbnQ+PjtcblxuICBpc09wZW4gPSBmYWxzZTtcbiAgaXNQb3NpdGlvbmVkID0gZmFsc2U7XG4gIGlzU3VibWVudVBvc2l0aW9uZWQgPSBmYWxzZTtcbiAgaXRlbXM6IENvbnRleHRNZW51SXRlbVtdID0gW107XG5cbiAgb3BlblN1Ym1lbnVJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIGFjdGl2ZVN1Ym1lbnVUcmlnZ2VyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsOyAvLyBTdG9yZSB0aGUgYnV0dG9uIHRoYXQgdHJpZ2dlcmVkIHRoZSBzdWJtZW51XG5cbiAgYWN0aXZlSW5kZXggPSAtMTtcbiAgcHJpdmF0ZSBzdGF0ZVN1YnNjcmlwdGlvbjogYW55O1xuICBwcml2YXRlIHN1Ym1lbnVUaW1lb3V0OiBhbnk7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGNuID0gY247XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5zdGF0ZVN1YnNjcmlwdGlvbiA9IHRoaXMuY29udGV4dE1lbnVTZXJ2aWNlLnN0YXRlQ2hhbmdlZC5zdWJzY3JpYmUoKHN0YXRlOiBDb250ZXh0TWVudVN0YXRlKSA9PiB7XG4gICAgICB0aGlzLmlzT3BlbiA9IHN0YXRlLmlzT3BlbjtcbiAgICAgIHRoaXMuaXRlbXMgPSBzdGF0ZS5pdGVtcztcblxuICAgICAgaWYgKHN0YXRlLmlzT3Blbikge1xuICAgICAgICB0aGlzLmFjdGl2ZUluZGV4ID0gLTE7XG4gICAgICAgIHRoaXMuaXNQb3NpdGlvbmVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgICAgICB0aGlzLnBvc2l0aW9uTWVudSgpO1xuICAgICAgICAgIHRoaXMuZm9jdXNGaXJzdEl0ZW0oKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmNsb3NlU3VibWVudSgpO1xuICAgICAgICB0aGlzLmFjdGl2ZUluZGV4ID0gLTE7XG4gICAgICAgIHRoaXMuaXNQb3NpdGlvbmVkID0gZmFsc2U7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBIZWxwZXIgdG8gZ2V0IGl0ZW1zIGZvciB0aGUgY3VycmVudGx5IG9wZW4gc3VibWVudVxuICBnZXQgYWN0aXZlU3VibWVudUl0ZW1zKCk6IENvbnRleHRNZW51SXRlbVtdIHtcbiAgICBpZiAoIXRoaXMub3BlblN1Ym1lbnVJZCkgcmV0dXJuIFtdO1xuICAgIHJldHVybiB0aGlzLml0ZW1zLmZpbmQoaSA9PiBpLmlkID09PSB0aGlzLm9wZW5TdWJtZW51SWQpPy5zdWJtZW51IHx8IFtdO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6Y2xpY2snLCBbJyRldmVudCddKVxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDpjb250ZXh0bWVudScsIFsnJGV2ZW50J10pXG4gIG9uRG9jdW1lbnRFdmVudHMoZXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICBpZiAoIXRoaXMuaXNPcGVuKSByZXR1cm47XG5cbiAgICAvLyBDaGVjayBpZiBjbGljayBpcyBpbnNpZGUgbWFpbiBtZW51IE9SIHRoZSBhY3RpdmUgc3VibWVudVxuICAgIGNvbnN0IGNsaWNrZWRJbnNpZGVNZW51ID0gdGhpcy5tZW51RWxlbWVudD8ubmF0aXZlRWxlbWVudC5jb250YWlucyhldmVudC50YXJnZXQgYXMgTm9kZSk7XG4gICAgY29uc3QgY2xpY2tlZEluc2lkZVN1Ym1lbnUgPSB0aGlzLnN1Ym1lbnVFbGVtZW50Py5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKGV2ZW50LnRhcmdldCBhcyBOb2RlKTtcblxuICAgIGlmIChjbGlja2VkSW5zaWRlTWVudSB8fCBjbGlja2VkSW5zaWRlU3VibWVudSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuY29udGV4dE1lbnVTZXJ2aWNlLmNsb3NlKCk7XG4gIH1cblxuICBhc3luYyBwb3NpdGlvbk1lbnUoKSB7XG4gICAgaWYgKHRoaXMubWVudUVsZW1lbnQ/Lm5hdGl2ZUVsZW1lbnQpIHtcbiAgICAgIHRoaXMuaXNQb3NpdGlvbmVkID0gZmFsc2U7XG4gICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICBhd2FpdCB0aGlzLmNvbnRleHRNZW51U2VydmljZS5wb3NpdGlvbk1lbnUodGhpcy5tZW51RWxlbWVudC5uYXRpdmVFbGVtZW50KTtcbiAgICAgIHRoaXMuaXNQb3NpdGlvbmVkID0gdHJ1ZTtcbiAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIC8vIEZvY3VzIHRoZSBtZW51IGNvbnRhaW5lciBzbyBBcnJvdy9FbnRlci9Fc2NhcGUga2V5ZG93biBoYW5kbGVycyBmaXJlLlxuICAgICAgdGhpcy5tZW51RWxlbWVudC5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gICAgfVxuICB9XG5cbiAgZm9jdXNGaXJzdEl0ZW0oKSB7XG4gICAgY29uc3QgZmlyc3RFbmFibGVkSW5kZXggPSB0aGlzLml0ZW1zLmZpbmRJbmRleChpdGVtID0+ICFpdGVtLmRpc2FibGVkICYmICFpdGVtLnNlcGFyYXRvcik7XG4gICAgaWYgKGZpcnN0RW5hYmxlZEluZGV4ICE9PSAtMSkge1xuICAgICAgdGhpcy5hY3RpdmVJbmRleCA9IGZpcnN0RW5hYmxlZEluZGV4O1xuICAgIH1cbiAgfVxuXG4gIG9uSXRlbUNsaWNrKGl0ZW06IENvbnRleHRNZW51SXRlbSkge1xuICAgIGlmIChpdGVtLmRpc2FibGVkIHx8IGl0ZW0uc2VwYXJhdG9yKSByZXR1cm47XG5cbiAgICBpZiAoaXRlbS5zdWJtZW51KSB7XG4gICAgICAvLyBUb2dnbGUgbG9naWMgaGFuZGxlZCBieSBlbnRlci9sZWF2ZSBtb3N0bHksIGJ1dCBjbGljayBjYW4gZm9yY2UgdG9nZ2xlXG4gICAgICBpZiAodGhpcy5vcGVuU3VibWVudUlkID09PSBpdGVtLmlkKSB7XG4gICAgICAgIHRoaXMuY2xvc2VTdWJtZW51KCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBXZSBuZWVkIHRoZSBidXR0b24gcmVmIHRvIG9wZW4gaXQgdmlhIGNsaWNrLiBcbiAgICAgICAgLy8gSW1wbGVtZW50YXRpb24gZGV0YWlsOiBIb3ZlciBpcyBwcmVmZXJyZWQgZm9yIHN1Ym1lbnVzLlxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmNvbnRleHRNZW51U2VydmljZS5wZXJmb3JtQWN0aW9uKGl0ZW0uaWQhKTtcbiAgICB9XG4gIH1cblxuICBvbkl0ZW1Nb3VzZUVudGVyKGl0ZW06IENvbnRleHRNZW51SXRlbSwgdHJpZ2dlcjogSFRNTEJ1dHRvbkVsZW1lbnQpIHtcbiAgICBpZiAoaXRlbS5kaXNhYmxlZCB8fCBpdGVtLnNlcGFyYXRvcikgcmV0dXJuO1xuXG4gICAgLy8gQ2xlYXIgYW55IHBlbmRpbmcgY2xvc2UgYWN0aW9uc1xuICAgIGNsZWFyVGltZW91dCh0aGlzLnN1Ym1lbnVUaW1lb3V0KTtcblxuICAgIHRoaXMuc3VibWVudVRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIGlmIChpdGVtLnN1Ym1lbnUpIHtcbiAgICAgICAgdGhpcy5vcGVuU3VibWVudUlkID0gaXRlbS5pZCE7XG4gICAgICAgIHRoaXMuYWN0aXZlU3VibWVudVRyaWdnZXIgPSB0cmlnZ2VyOyAvLyBTYXZlIHRoZSB0cmlnZ2VyIGZvciBwb3NpdGlvbmluZ1xuICAgICAgICB0aGlzLnBvc2l0aW9uU3VibWVudSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5jbG9zZVN1Ym1lbnUoKTtcbiAgICAgIH1cbiAgICB9LCAxNTApO1xuICB9XG5cbiAgb25JdGVtTW91c2VMZWF2ZSgpIHtcbiAgICAvLyBXZSBkb24ndCBjbG9zZSBpbW1lZGlhdGVseTsgd2Ugd2FpdCB0byBzZWUgaWYgdGhlIHVzZXIgZW50ZXJzIHRoZSBzdWJtZW51XG4gICAgLy8gTG9naWMgaGFuZGxlZCBieSB0aGUgdGltZW91dCBpbiBgb25JdGVtTW91c2VFbnRlcmAgb2YgYSBzaWJsaW5nLCBcbiAgICAvLyBvciB3ZSBjb3VsZCBhZGQgYSB0aW1lb3V0IGhlcmUgdG8gY2xvc2UgaWYgdGhleSBnbyBub3doZXJlLlxuICB9XG5cbiAgb25TdWJtZW51TW91c2VFbnRlcigpIHtcbiAgICAvLyBJZiB1c2VyIGlzIGhvdmVyaW5nIHRoZSBzdWJtZW51LCBrZWVwIGl0IG9wZW5cbiAgICBjbGVhclRpbWVvdXQodGhpcy5zdWJtZW51VGltZW91dCk7XG4gIH1cblxuICBvblN1Ym1lbnVNb3VzZUxlYXZlKCkge1xuICAgIC8vIElmIHVzZXIgbGVhdmVzIHN1Ym1lbnUsIHN0YW5kYXJkIGJlaGF2aW9yIGlzIHVzdWFsbHkgdG8ga2VlcCBpdCBvcGVuIFxuICAgIC8vIHVudGlsIHRoZXkgaG92ZXIgYW5vdGhlciBtYWluIGl0ZW0gb3IgY2xpY2sgYXdheS5cbiAgfVxuXG4gIHByaXZhdGUgY2xvc2VTdWJtZW51KCkge1xuICAgIHRoaXMub3BlblN1Ym1lbnVJZCA9IG51bGw7XG4gICAgdGhpcy5hY3RpdmVTdWJtZW51VHJpZ2dlciA9IG51bGw7XG4gICAgdGhpcy5pc1N1Ym1lbnVQb3NpdGlvbmVkID0gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHBvc2l0aW9uU3VibWVudSgpIHtcbiAgICB0aGlzLmlzU3VibWVudVBvc2l0aW9uZWQgPSBmYWxzZTtcbiAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7IC8vIFJlbmRlciB0aGUgc3VibWVudSBET01cblxuICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZShhc3luYyAoKSA9PiB7XG4gICAgICBpZiAodGhpcy5hY3RpdmVTdWJtZW51VHJpZ2dlciAmJiB0aGlzLnN1Ym1lbnVFbGVtZW50KSB7XG4gICAgICAgIGF3YWl0IHRoaXMuY29udGV4dE1lbnVTZXJ2aWNlLnBvc2l0aW9uU3VibWVudShcbiAgICAgICAgICB0aGlzLmFjdGl2ZVN1Ym1lbnVUcmlnZ2VyLFxuICAgICAgICAgIHRoaXMuc3VibWVudUVsZW1lbnQubmF0aXZlRWxlbWVudFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmlzU3VibWVudVBvc2l0aW9uZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBvblN1Ykl0ZW1DbGljayhpdGVtOiBDb250ZXh0TWVudUl0ZW0pIHtcbiAgICBpZiAoaXRlbS5kaXNhYmxlZCB8fCBpdGVtLnNlcGFyYXRvcikgcmV0dXJuO1xuICAgIHRoaXMuY29udGV4dE1lbnVTZXJ2aWNlLnBlcmZvcm1BY3Rpb24oaXRlbS5pZCEpO1xuICB9XG5cbiAgb25LZXlEb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgc3dpdGNoIChldmVudC5rZXkpIHtcbiAgICAgIGNhc2UgJ0Fycm93RG93bic6XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMubmF2aWdhdGUoMSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnQXJyb3dVcCc6XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMubmF2aWdhdGUoLTEpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ0Fycm93UmlnaHQnOlxuICAgICAgICBjb25zdCBjdXJyZW50SXRlbSA9IHRoaXMuaXRlbXNbdGhpcy5hY3RpdmVJbmRleF07XG4gICAgICAgIGlmIChjdXJyZW50SXRlbT8uc3VibWVudSkge1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgLy8gRm9yY2Ugb3BlbiBzdWJtZW51IHZpYSBrZXlib2FyZFxuICAgICAgICAgIHRoaXMub3BlblN1Ym1lbnVJZCA9IGN1cnJlbnRJdGVtLmlkITtcbiAgICAgICAgICBjb25zdCB0cmlnZ2VyID0gdGhpcy5pdGVtQnV0dG9ucy50b0FycmF5KClbdGhpcy5hY3RpdmVJbmRleF0/Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgICAgICAgaWYgKHRyaWdnZXIpIHtcbiAgICAgICAgICAgIHRoaXMuYWN0aXZlU3VibWVudVRyaWdnZXIgPSB0cmlnZ2VyO1xuICAgICAgICAgICAgdGhpcy5wb3NpdGlvblN1Ym1lbnUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdBcnJvd0xlZnQnOlxuICAgICAgICBpZiAodGhpcy5vcGVuU3VibWVudUlkKSB7XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICB0aGlzLmNsb3NlU3VibWVudSgpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnRW50ZXInOlxuICAgICAgICBpZiAodGhpcy5hY3RpdmVJbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIHRoaXMub25JdGVtQ2xpY2sodGhpcy5pdGVtc1t0aGlzLmFjdGl2ZUluZGV4XSk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdFc2NhcGUnOlxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLmNvbnRleHRNZW51U2VydmljZS5jbG9zZSgpO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG5hdmlnYXRlKGRpcmVjdGlvbjogbnVtYmVyKSB7XG4gICAgbGV0IG5leHRJbmRleCA9IHRoaXMuYWN0aXZlSW5kZXggKyBkaXJlY3Rpb247XG4gICAgY29uc3QgY291bnQgPSB0aGlzLml0ZW1zLmxlbmd0aDtcbiAgICB3aGlsZSAobmV4dEluZGV4ID49IDAgJiYgbmV4dEluZGV4IDwgY291bnQpIHtcbiAgICAgIGNvbnN0IGl0ZW0gPSB0aGlzLml0ZW1zW25leHRJbmRleF07XG4gICAgICBpZiAoIWl0ZW0uZGlzYWJsZWQgJiYgIWl0ZW0uc2VwYXJhdG9yKSB7XG4gICAgICAgIHRoaXMuYWN0aXZlSW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIG5leHRJbmRleCArPSBkaXJlY3Rpb247XG4gICAgfVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6a2V5ZG93bi5lc2NhcGUnKVxuICBvbkVzY2FwZSgpIHtcbiAgICB0aGlzLmNvbnRleHRNZW51U2VydmljZS5jbG9zZSgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgaWYgKHRoaXMuc3RhdGVTdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMuc3RhdGVTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gICAgY2xlYXJUaW1lb3V0KHRoaXMuc3VibWVudVRpbWVvdXQpO1xuICB9XG59Il19
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Injectable, EventEmitter } from '@angular/core';
|
|
2
|
+
import { computePosition, offset, shift, flip, size } from '@floating-ui/dom';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export class ContextMenuService {
|
|
5
|
+
_state = {
|
|
6
|
+
x: 0,
|
|
7
|
+
y: 0,
|
|
8
|
+
items: [],
|
|
9
|
+
isOpen: false
|
|
10
|
+
};
|
|
11
|
+
stateChanged = new EventEmitter();
|
|
12
|
+
open(config) {
|
|
13
|
+
const { event, items = [], triggerElement, onAction } = config;
|
|
14
|
+
// Prevent browser context menu
|
|
15
|
+
event.preventDefault();
|
|
16
|
+
this._state = {
|
|
17
|
+
x: event.clientX,
|
|
18
|
+
y: event.clientY,
|
|
19
|
+
items,
|
|
20
|
+
isOpen: true,
|
|
21
|
+
triggerElement,
|
|
22
|
+
onAction
|
|
23
|
+
};
|
|
24
|
+
this.stateChanged.emit(this._state);
|
|
25
|
+
}
|
|
26
|
+
close() {
|
|
27
|
+
this._state = { ...this._state, isOpen: false };
|
|
28
|
+
this.stateChanged.emit(this._state);
|
|
29
|
+
}
|
|
30
|
+
async positionMenu(menuElement) {
|
|
31
|
+
const state = this._state;
|
|
32
|
+
if (!state.isOpen || !menuElement)
|
|
33
|
+
return;
|
|
34
|
+
// Create a precise virtual element for the mouse coordinates
|
|
35
|
+
const virtualEl = {
|
|
36
|
+
getBoundingClientRect() {
|
|
37
|
+
return {
|
|
38
|
+
width: 0,
|
|
39
|
+
height: 0,
|
|
40
|
+
x: state.x,
|
|
41
|
+
y: state.y,
|
|
42
|
+
top: state.y,
|
|
43
|
+
left: state.x,
|
|
44
|
+
right: state.x,
|
|
45
|
+
bottom: state.y,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const { x, y } = await computePosition(virtualEl, menuElement, {
|
|
50
|
+
placement: 'bottom-start', // Standard: Menu top-left aligns with mouse
|
|
51
|
+
strategy: 'fixed',
|
|
52
|
+
middleware: [
|
|
53
|
+
offset(2), // Slight offset so mouse isn't covering the first pixel
|
|
54
|
+
flip({
|
|
55
|
+
padding: 10,
|
|
56
|
+
fallbackPlacements: ['bottom-end', 'top-start', 'top-end']
|
|
57
|
+
}),
|
|
58
|
+
shift({ padding: 10 }),
|
|
59
|
+
size({
|
|
60
|
+
apply({ availableHeight, availableWidth, elements }) {
|
|
61
|
+
Object.assign(elements.floating.style, {
|
|
62
|
+
maxHeight: `${Math.max(100, availableHeight - 16)}px`,
|
|
63
|
+
maxWidth: `${Math.max(200, availableWidth - 16)}px`,
|
|
64
|
+
overflowY: 'auto'
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
]
|
|
69
|
+
});
|
|
70
|
+
Object.assign(menuElement.style, {
|
|
71
|
+
position: 'fixed',
|
|
72
|
+
left: '0',
|
|
73
|
+
top: '0',
|
|
74
|
+
transform: `translate(${Math.round(x)}px, ${Math.round(y)}px)`
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
async positionSubmenu(triggerElement, submenuElement) {
|
|
78
|
+
if (!triggerElement || !submenuElement)
|
|
79
|
+
return;
|
|
80
|
+
const { x, y } = await computePosition(triggerElement, submenuElement, {
|
|
81
|
+
placement: 'right-start', // Standard: Submenu opens to the right
|
|
82
|
+
strategy: 'fixed',
|
|
83
|
+
middleware: [
|
|
84
|
+
offset(-4), // Overlap slightly with parent menu
|
|
85
|
+
flip({
|
|
86
|
+
padding: 10,
|
|
87
|
+
fallbackPlacements: ['left-start', 'bottom-start']
|
|
88
|
+
}),
|
|
89
|
+
shift({ padding: 10 }),
|
|
90
|
+
size({
|
|
91
|
+
apply({ availableHeight, availableWidth, elements }) {
|
|
92
|
+
Object.assign(elements.floating.style, {
|
|
93
|
+
maxHeight: `${Math.max(100, availableHeight - 16)}px`,
|
|
94
|
+
maxWidth: `${Math.max(200, availableWidth - 16)}px`,
|
|
95
|
+
overflowY: 'auto'
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
]
|
|
100
|
+
});
|
|
101
|
+
Object.assign(submenuElement.style, {
|
|
102
|
+
position: 'fixed',
|
|
103
|
+
left: '0',
|
|
104
|
+
top: '0',
|
|
105
|
+
transform: `translate(${Math.round(x)}px, ${Math.round(y)}px)`
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
performAction(actionId) {
|
|
109
|
+
this._state.onAction?.(actionId);
|
|
110
|
+
this.close();
|
|
111
|
+
}
|
|
112
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContextMenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
113
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContextMenuService, providedIn: 'root' });
|
|
114
|
+
}
|
|
115
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ContextMenuService, decorators: [{
|
|
116
|
+
type: Injectable,
|
|
117
|
+
args: [{
|
|
118
|
+
providedIn: 'root'
|
|
119
|
+
}]
|
|
120
|
+
}] });
|
|
121
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC1tZW51LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy90b2xsZS9zcmMvbGliL2NvbnRleHQtbWVudS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7O0FBMkI5RSxNQUFNLE9BQU8sa0JBQWtCO0lBQ3JCLE1BQU0sR0FBcUI7UUFDakMsQ0FBQyxFQUFFLENBQUM7UUFDSixDQUFDLEVBQUUsQ0FBQztRQUNKLEtBQUssRUFBRSxFQUFFO1FBQ1QsTUFBTSxFQUFFLEtBQUs7S0FDZCxDQUFDO0lBRU8sWUFBWSxHQUFHLElBQUksWUFBWSxFQUFvQixDQUFDO0lBRTdELElBQUksQ0FBQyxNQUtKO1FBQ0MsTUFBTSxFQUFFLEtBQUssRUFBRSxLQUFLLEdBQUcsRUFBRSxFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQUUsR0FBRyxNQUFNLENBQUM7UUFFL0QsK0JBQStCO1FBQy9CLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUV2QixJQUFJLENBQUMsTUFBTSxHQUFHO1lBQ1osQ0FBQyxFQUFFLEtBQUssQ0FBQyxPQUFPO1lBQ2hCLENBQUMsRUFBRSxLQUFLLENBQUMsT0FBTztZQUNoQixLQUFLO1lBQ0wsTUFBTSxFQUFFLElBQUk7WUFDWixjQUFjO1lBQ2QsUUFBUTtTQUNULENBQUM7UUFFRixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELEtBQUs7UUFDSCxJQUFJLENBQUMsTUFBTSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQztRQUNoRCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELEtBQUssQ0FBQyxZQUFZLENBQUMsV0FBd0I7UUFDekMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztRQUMxQixJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sSUFBSSxDQUFDLFdBQVc7WUFBRSxPQUFPO1FBRTFDLDZEQUE2RDtRQUM3RCxNQUFNLFNBQVMsR0FBRztZQUNoQixxQkFBcUI7Z0JBQ25CLE9BQU87b0JBQ0wsS0FBSyxFQUFFLENBQUM7b0JBQ1IsTUFBTSxFQUFFLENBQUM7b0JBQ1QsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO29CQUNWLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztvQkFDVixHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7b0JBQ1osSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO29CQUNiLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztvQkFDZCxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7aUJBQ2hCLENBQUM7WUFDSixDQUFDO1NBQ0YsQ0FBQztRQUVGLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsTUFBTSxlQUFlLENBQUMsU0FBZ0IsRUFBRSxXQUFXLEVBQUU7WUFDcEUsU0FBUyxFQUFFLGNBQWMsRUFBRSw0Q0FBNEM7WUFDdkUsUUFBUSxFQUFFLE9BQU87WUFDakIsVUFBVSxFQUFFO2dCQUNWLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSx3REFBd0Q7Z0JBQ25FLElBQUksQ0FBQztvQkFDSCxPQUFPLEVBQUUsRUFBRTtvQkFDWCxrQkFBa0IsRUFBRSxDQUFDLFlBQVksRUFBRSxXQUFXLEVBQUUsU0FBUyxDQUFDO2lCQUMzRCxDQUFDO2dCQUNGLEtBQUssQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQztnQkFDdEIsSUFBSSxDQUFDO29CQUNILEtBQUssQ0FBQyxFQUFFLGVBQWUsRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUFFO3dCQUNqRCxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFOzRCQUNyQyxTQUFTLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxlQUFlLEdBQUcsRUFBRSxDQUFDLElBQUk7NEJBQ3JELFFBQVEsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLGNBQWMsR0FBRyxFQUFFLENBQUMsSUFBSTs0QkFDbkQsU0FBUyxFQUFFLE1BQU07eUJBQ2xCLENBQUMsQ0FBQztvQkFDTCxDQUFDO2lCQUNGLENBQUM7YUFDSDtTQUNGLENBQUMsQ0FBQztRQUVILE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRTtZQUMvQixRQUFRLEVBQUUsT0FBTztZQUNqQixJQUFJLEVBQUUsR0FBRztZQUNULEdBQUcsRUFBRSxHQUFHO1lBQ1IsU0FBUyxFQUFFLGFBQWEsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLO1NBQy9ELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsZUFBZSxDQUFDLGNBQTJCLEVBQUUsY0FBMkI7UUFDNUUsSUFBSSxDQUFDLGNBQWMsSUFBSSxDQUFDLGNBQWM7WUFBRSxPQUFPO1FBRS9DLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEdBQUcsTUFBTSxlQUFlLENBQUMsY0FBYyxFQUFFLGNBQWMsRUFBRTtZQUNyRSxTQUFTLEVBQUUsYUFBYSxFQUFFLHVDQUF1QztZQUNqRSxRQUFRLEVBQUUsT0FBTztZQUNqQixVQUFVLEVBQUU7Z0JBQ1YsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsb0NBQW9DO2dCQUNoRCxJQUFJLENBQUM7b0JBQ0gsT0FBTyxFQUFFLEVBQUU7b0JBQ1gsa0JBQWtCLEVBQUUsQ0FBQyxZQUFZLEVBQUUsY0FBYyxDQUFDO2lCQUNuRCxDQUFDO2dCQUNGLEtBQUssQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQztnQkFDdEIsSUFBSSxDQUFDO29CQUNILEtBQUssQ0FBQyxFQUFFLGVBQWUsRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUFFO3dCQUNqRCxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFOzRCQUNyQyxTQUFTLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxlQUFlLEdBQUcsRUFBRSxDQUFDLElBQUk7NEJBQ3JELFFBQVEsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLGNBQWMsR0FBRyxFQUFFLENBQUMsSUFBSTs0QkFDbkQsU0FBUyxFQUFFLE1BQU07eUJBQ2xCLENBQUMsQ0FBQztvQkFDTCxDQUFDO2lCQUNGLENBQUM7YUFDSDtTQUNGLENBQUMsQ0FBQztRQUVILE1BQU0sQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQUssRUFBRTtZQUNsQyxRQUFRLEVBQUUsT0FBTztZQUNqQixJQUFJLEVBQUUsR0FBRztZQUNULEdBQUcsRUFBRSxHQUFHO1lBQ1IsU0FBUyxFQUFFLGFBQWEsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLO1NBQy9ELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxhQUFhLENBQUMsUUFBZ0I7UUFDNUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNqQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDZixDQUFDO3dHQTVIVSxrQkFBa0I7NEdBQWxCLGtCQUFrQixjQUZqQixNQUFNOzs0RkFFUCxrQkFBa0I7a0JBSDlCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBjb21wdXRlUG9zaXRpb24sIG9mZnNldCwgc2hpZnQsIGZsaXAsIHNpemUgfSBmcm9tICdAZmxvYXRpbmctdWkvZG9tJztcblxuZXhwb3J0IHR5cGUgQ29udGV4dE1lbnVJdGVtID0ge1xuICBpZD86IHN0cmluZztcbiAgbGFiZWw/OiBzdHJpbmc7XG4gIGljb24/OiBzdHJpbmc7XG4gIGRpc2FibGVkPzogYm9vbGVhbjtcbiAgZGVzdHJ1Y3RpdmU/OiBib29sZWFuO1xuICBzZXBhcmF0b3I/OiBib29sZWFuO1xuICBzdWJtZW51PzogQ29udGV4dE1lbnVJdGVtW107XG4gIHNob3J0Y3V0Pzogc3RyaW5nO1xuICBjaGVja2VkPzogYm9vbGVhbjtcbiAgdHlwZT86ICdkZWZhdWx0JyB8ICdjaGVja2JveCcgfCAncmFkaW8nO1xufVxuXG5leHBvcnQgdHlwZSBDb250ZXh0TWVudVN0YXRlID0ge1xuICB4OiBudW1iZXI7XG4gIHk6IG51bWJlcjtcbiAgaXRlbXM6IENvbnRleHRNZW51SXRlbVtdO1xuICBpc09wZW46IGJvb2xlYW47XG4gIHRyaWdnZXJFbGVtZW50PzogSFRNTEVsZW1lbnQ7XG4gIG9uQWN0aW9uPzogKGFjdGlvbklkOiBzdHJpbmcpID0+IHZvaWQ7XG59XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIENvbnRleHRNZW51U2VydmljZSB7XG4gIHByaXZhdGUgX3N0YXRlOiBDb250ZXh0TWVudVN0YXRlID0ge1xuICAgIHg6IDAsXG4gICAgeTogMCxcbiAgICBpdGVtczogW10sXG4gICAgaXNPcGVuOiBmYWxzZVxuICB9O1xuXG4gIHJlYWRvbmx5IHN0YXRlQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8Q29udGV4dE1lbnVTdGF0ZT4oKTtcblxuICBvcGVuKGNvbmZpZzoge1xuICAgIGV2ZW50OiBNb3VzZUV2ZW50O1xuICAgIGl0ZW1zPzogQ29udGV4dE1lbnVJdGVtW107XG4gICAgdHJpZ2dlckVsZW1lbnQ/OiBIVE1MRWxlbWVudDtcbiAgICBvbkFjdGlvbj86IChhY3Rpb25JZDogc3RyaW5nKSA9PiB2b2lkO1xuICB9KSB7XG4gICAgY29uc3QgeyBldmVudCwgaXRlbXMgPSBbXSwgdHJpZ2dlckVsZW1lbnQsIG9uQWN0aW9uIH0gPSBjb25maWc7XG5cbiAgICAvLyBQcmV2ZW50IGJyb3dzZXIgY29udGV4dCBtZW51XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgIHRoaXMuX3N0YXRlID0ge1xuICAgICAgeDogZXZlbnQuY2xpZW50WCxcbiAgICAgIHk6IGV2ZW50LmNsaWVudFksXG4gICAgICBpdGVtcyxcbiAgICAgIGlzT3BlbjogdHJ1ZSxcbiAgICAgIHRyaWdnZXJFbGVtZW50LFxuICAgICAgb25BY3Rpb25cbiAgICB9O1xuXG4gICAgdGhpcy5zdGF0ZUNoYW5nZWQuZW1pdCh0aGlzLl9zdGF0ZSk7XG4gIH1cblxuICBjbG9zZSgpIHtcbiAgICB0aGlzLl9zdGF0ZSA9IHsgLi4udGhpcy5fc3RhdGUsIGlzT3BlbjogZmFsc2UgfTtcbiAgICB0aGlzLnN0YXRlQ2hhbmdlZC5lbWl0KHRoaXMuX3N0YXRlKTtcbiAgfVxuXG4gIGFzeW5jIHBvc2l0aW9uTWVudShtZW51RWxlbWVudDogSFRNTEVsZW1lbnQpIHtcbiAgICBjb25zdCBzdGF0ZSA9IHRoaXMuX3N0YXRlO1xuICAgIGlmICghc3RhdGUuaXNPcGVuIHx8ICFtZW51RWxlbWVudCkgcmV0dXJuO1xuXG4gICAgLy8gQ3JlYXRlIGEgcHJlY2lzZSB2aXJ0dWFsIGVsZW1lbnQgZm9yIHRoZSBtb3VzZSBjb29yZGluYXRlc1xuICAgIGNvbnN0IHZpcnR1YWxFbCA9IHtcbiAgICAgIGdldEJvdW5kaW5nQ2xpZW50UmVjdCgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB3aWR0aDogMCxcbiAgICAgICAgICBoZWlnaHQ6IDAsXG4gICAgICAgICAgeDogc3RhdGUueCxcbiAgICAgICAgICB5OiBzdGF0ZS55LFxuICAgICAgICAgIHRvcDogc3RhdGUueSxcbiAgICAgICAgICBsZWZ0OiBzdGF0ZS54LFxuICAgICAgICAgIHJpZ2h0OiBzdGF0ZS54LFxuICAgICAgICAgIGJvdHRvbTogc3RhdGUueSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgY29uc3QgeyB4LCB5IH0gPSBhd2FpdCBjb21wdXRlUG9zaXRpb24odmlydHVhbEVsIGFzIGFueSwgbWVudUVsZW1lbnQsIHtcbiAgICAgIHBsYWNlbWVudDogJ2JvdHRvbS1zdGFydCcsIC8vIFN0YW5kYXJkOiBNZW51IHRvcC1sZWZ0IGFsaWducyB3aXRoIG1vdXNlXG4gICAgICBzdHJhdGVneTogJ2ZpeGVkJyxcbiAgICAgIG1pZGRsZXdhcmU6IFtcbiAgICAgICAgb2Zmc2V0KDIpLCAvLyBTbGlnaHQgb2Zmc2V0IHNvIG1vdXNlIGlzbid0IGNvdmVyaW5nIHRoZSBmaXJzdCBwaXhlbFxuICAgICAgICBmbGlwKHtcbiAgICAgICAgICBwYWRkaW5nOiAxMCxcbiAgICAgICAgICBmYWxsYmFja1BsYWNlbWVudHM6IFsnYm90dG9tLWVuZCcsICd0b3Atc3RhcnQnLCAndG9wLWVuZCddXG4gICAgICAgIH0pLFxuICAgICAgICBzaGlmdCh7IHBhZGRpbmc6IDEwIH0pLFxuICAgICAgICBzaXplKHtcbiAgICAgICAgICBhcHBseSh7IGF2YWlsYWJsZUhlaWdodCwgYXZhaWxhYmxlV2lkdGgsIGVsZW1lbnRzIH0pIHtcbiAgICAgICAgICAgIE9iamVjdC5hc3NpZ24oZWxlbWVudHMuZmxvYXRpbmcuc3R5bGUsIHtcbiAgICAgICAgICAgICAgbWF4SGVpZ2h0OiBgJHtNYXRoLm1heCgxMDAsIGF2YWlsYWJsZUhlaWdodCAtIDE2KX1weGAsXG4gICAgICAgICAgICAgIG1heFdpZHRoOiBgJHtNYXRoLm1heCgyMDAsIGF2YWlsYWJsZVdpZHRoIC0gMTYpfXB4YCxcbiAgICAgICAgICAgICAgb3ZlcmZsb3dZOiAnYXV0bydcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgIF1cbiAgICB9KTtcblxuICAgIE9iamVjdC5hc3NpZ24obWVudUVsZW1lbnQuc3R5bGUsIHtcbiAgICAgIHBvc2l0aW9uOiAnZml4ZWQnLFxuICAgICAgbGVmdDogJzAnLFxuICAgICAgdG9wOiAnMCcsXG4gICAgICB0cmFuc2Zvcm06IGB0cmFuc2xhdGUoJHtNYXRoLnJvdW5kKHgpfXB4LCAke01hdGgucm91bmQoeSl9cHgpYFxuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgcG9zaXRpb25TdWJtZW51KHRyaWdnZXJFbGVtZW50OiBIVE1MRWxlbWVudCwgc3VibWVudUVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG4gICAgaWYgKCF0cmlnZ2VyRWxlbWVudCB8fCAhc3VibWVudUVsZW1lbnQpIHJldHVybjtcblxuICAgIGNvbnN0IHsgeCwgeSB9ID0gYXdhaXQgY29tcHV0ZVBvc2l0aW9uKHRyaWdnZXJFbGVtZW50LCBzdWJtZW51RWxlbWVudCwge1xuICAgICAgcGxhY2VtZW50OiAncmlnaHQtc3RhcnQnLCAvLyBTdGFuZGFyZDogU3VibWVudSBvcGVucyB0byB0aGUgcmlnaHRcbiAgICAgIHN0cmF0ZWd5OiAnZml4ZWQnLFxuICAgICAgbWlkZGxld2FyZTogW1xuICAgICAgICBvZmZzZXQoLTQpLCAvLyBPdmVybGFwIHNsaWdodGx5IHdpdGggcGFyZW50IG1lbnVcbiAgICAgICAgZmxpcCh7XG4gICAgICAgICAgcGFkZGluZzogMTAsXG4gICAgICAgICAgZmFsbGJhY2tQbGFjZW1lbnRzOiBbJ2xlZnQtc3RhcnQnLCAnYm90dG9tLXN0YXJ0J11cbiAgICAgICAgfSksXG4gICAgICAgIHNoaWZ0KHsgcGFkZGluZzogMTAgfSksXG4gICAgICAgIHNpemUoe1xuICAgICAgICAgIGFwcGx5KHsgYXZhaWxhYmxlSGVpZ2h0LCBhdmFpbGFibGVXaWR0aCwgZWxlbWVudHMgfSkge1xuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihlbGVtZW50cy5mbG9hdGluZy5zdHlsZSwge1xuICAgICAgICAgICAgICBtYXhIZWlnaHQ6IGAke01hdGgubWF4KDEwMCwgYXZhaWxhYmxlSGVpZ2h0IC0gMTYpfXB4YCxcbiAgICAgICAgICAgICAgbWF4V2lkdGg6IGAke01hdGgubWF4KDIwMCwgYXZhaWxhYmxlV2lkdGggLSAxNil9cHhgLFxuICAgICAgICAgICAgICBvdmVyZmxvd1k6ICdhdXRvJ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgXVxuICAgIH0pO1xuXG4gICAgT2JqZWN0LmFzc2lnbihzdWJtZW51RWxlbWVudC5zdHlsZSwge1xuICAgICAgcG9zaXRpb246ICdmaXhlZCcsXG4gICAgICBsZWZ0OiAnMCcsXG4gICAgICB0b3A6ICcwJyxcbiAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZSgke01hdGgucm91bmQoeCl9cHgsICR7TWF0aC5yb3VuZCh5KX1weClgXG4gICAgfSk7XG4gIH1cblxuICBwZXJmb3JtQWN0aW9uKGFjdGlvbklkOiBzdHJpbmcpIHtcbiAgICB0aGlzLl9zdGF0ZS5vbkFjdGlvbj8uKGFjdGlvbklkKTtcbiAgICB0aGlzLmNsb3NlKCk7XG4gIH1cbn0iXX0=
|