@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,452 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Injectable, Input, Output, inject } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { BehaviorSubject, Subscription } from 'rxjs';
|
|
4
|
+
import { skip } from 'rxjs/operators';
|
|
5
|
+
import { cva } from 'class-variance-authority';
|
|
6
|
+
import { cn } from './utils/cn';
|
|
7
|
+
import * as i0 from "@angular/core";
|
|
8
|
+
import * as i1 from "@angular/common";
|
|
9
|
+
let sourceId = 0;
|
|
10
|
+
/**
|
|
11
|
+
* Coordinates a `tolle-sources` with its trigger, content and sources.
|
|
12
|
+
*
|
|
13
|
+
* The trigger has to report how many sources were projected into a sibling
|
|
14
|
+
* component, so every `tolle-source` registers here and the trigger renders
|
|
15
|
+
* from the resulting count.
|
|
16
|
+
*
|
|
17
|
+
* Provided on `SourcesComponent`, so each citation list gets its own instance.
|
|
18
|
+
*/
|
|
19
|
+
export class SourcesService {
|
|
20
|
+
openSource = new BehaviorSubject(false);
|
|
21
|
+
/** Emits whether the citation list is expanded. */
|
|
22
|
+
open$ = this.openSource.asObservable();
|
|
23
|
+
idsSource = new BehaviorSubject([]);
|
|
24
|
+
/** Emits the ids of the registered sources, in registration (DOM) order. */
|
|
25
|
+
ids$ = this.idsSource.asObservable();
|
|
26
|
+
/** True while the citation list is expanded. */
|
|
27
|
+
get open() {
|
|
28
|
+
return this.openSource.value;
|
|
29
|
+
}
|
|
30
|
+
/** How many sources are currently registered. */
|
|
31
|
+
get count() {
|
|
32
|
+
return this.idsSource.value.length;
|
|
33
|
+
}
|
|
34
|
+
setOpen(value) {
|
|
35
|
+
if (this.openSource.value !== value)
|
|
36
|
+
this.openSource.next(value);
|
|
37
|
+
}
|
|
38
|
+
toggle() {
|
|
39
|
+
this.setOpen(!this.openSource.value);
|
|
40
|
+
}
|
|
41
|
+
register(id) {
|
|
42
|
+
if (this.idsSource.value.includes(id))
|
|
43
|
+
return;
|
|
44
|
+
this.idsSource.next([...this.idsSource.value, id]);
|
|
45
|
+
}
|
|
46
|
+
unregister(id) {
|
|
47
|
+
this.idsSource.next(this.idsSource.value.filter((existing) => existing !== id));
|
|
48
|
+
}
|
|
49
|
+
/** Zero-based position of a source, or -1 when it is not registered. */
|
|
50
|
+
indexOf(id) {
|
|
51
|
+
return this.idsSource.value.indexOf(id);
|
|
52
|
+
}
|
|
53
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SourcesService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
54
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SourcesService });
|
|
55
|
+
}
|
|
56
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SourcesService, decorators: [{
|
|
57
|
+
type: Injectable
|
|
58
|
+
}] });
|
|
59
|
+
const sourcesVariants = cva('flex w-full flex-col gap-2 text-sm', {
|
|
60
|
+
variants: {
|
|
61
|
+
variant: {
|
|
62
|
+
default: '',
|
|
63
|
+
card: 'rounded-md border border-border bg-card p-3 text-card-foreground',
|
|
64
|
+
muted: 'rounded-md bg-muted p-3',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
defaultVariants: {
|
|
68
|
+
variant: 'default',
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
/**
|
|
72
|
+
* A collapsible list of the citations behind a response.
|
|
73
|
+
*
|
|
74
|
+
* Compose it from `tolle-sources-trigger`, `tolle-sources-content` and one
|
|
75
|
+
* `tolle-source` per citation — the trigger counts the sources for you.
|
|
76
|
+
* @new
|
|
77
|
+
*/
|
|
78
|
+
export class SourcesComponent {
|
|
79
|
+
/** Whether the citation list is expanded. @default false */
|
|
80
|
+
open = false;
|
|
81
|
+
/** Visual treatment of the list container. @default 'default' */
|
|
82
|
+
variant = 'default';
|
|
83
|
+
/** Extra Tailwind classes merged onto the list via `cn()` (last-wins). */
|
|
84
|
+
class = '';
|
|
85
|
+
/** Emitted with the new state whenever the list is expanded or collapsed. */
|
|
86
|
+
openChange = new EventEmitter();
|
|
87
|
+
service = inject(SourcesService);
|
|
88
|
+
cdr = inject(ChangeDetectorRef);
|
|
89
|
+
subscriptions = new Subscription();
|
|
90
|
+
/** True while an `open` input is being pushed into the service. */
|
|
91
|
+
applyingInput = false;
|
|
92
|
+
ngOnInit() {
|
|
93
|
+
this.service.setOpen(this.open);
|
|
94
|
+
// `skip(1)` drops the BehaviorSubject's current value so mounting never
|
|
95
|
+
// emits a spurious `openChange`.
|
|
96
|
+
this.subscriptions.add(this.service.open$.pipe(skip(1)).subscribe((open) => {
|
|
97
|
+
this.open = open;
|
|
98
|
+
this.cdr.markForCheck();
|
|
99
|
+
// Only user-driven toggles are worth reporting; echoing a change the
|
|
100
|
+
// parent just made would fight a `[(open)]` binding.
|
|
101
|
+
if (!this.applyingInput)
|
|
102
|
+
this.openChange.emit(open);
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
ngOnChanges(changes) {
|
|
106
|
+
if (changes['open'])
|
|
107
|
+
this.applyInput(this.open);
|
|
108
|
+
// A bound `class` input is written through Angular's styling path,
|
|
109
|
+
// which does not mark an OnPush view dirty on its own.
|
|
110
|
+
this.cdr.markForCheck();
|
|
111
|
+
}
|
|
112
|
+
applyInput(open) {
|
|
113
|
+
this.applyingInput = true;
|
|
114
|
+
try {
|
|
115
|
+
this.service.setOpen(open);
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
this.applyingInput = false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
ngOnDestroy() {
|
|
122
|
+
this.subscriptions.unsubscribe();
|
|
123
|
+
}
|
|
124
|
+
get computedClass() {
|
|
125
|
+
return cn(sourcesVariants({ variant: this.variant }), this.class);
|
|
126
|
+
}
|
|
127
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SourcesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
128
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: SourcesComponent, isStandalone: true, selector: "tolle-sources", inputs: { open: "open", variant: "variant", class: "class" }, outputs: { openChange: "openChange" }, providers: [SourcesService], usesOnChanges: true, ngImport: i0, template: `
|
|
129
|
+
<div [class]="computedClass" [attr.data-state]="open ? 'open' : 'closed'">
|
|
130
|
+
<ng-content></ng-content>
|
|
131
|
+
</div>
|
|
132
|
+
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
133
|
+
}
|
|
134
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SourcesComponent, decorators: [{
|
|
135
|
+
type: Component,
|
|
136
|
+
args: [{ selector: 'tolle-sources', standalone: true, imports: [CommonModule], providers: [SourcesService], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
137
|
+
<div [class]="computedClass" [attr.data-state]="open ? 'open' : 'closed'">
|
|
138
|
+
<ng-content></ng-content>
|
|
139
|
+
</div>
|
|
140
|
+
`, styles: [":host{display:block}\n"] }]
|
|
141
|
+
}], propDecorators: { open: [{
|
|
142
|
+
type: Input
|
|
143
|
+
}], variant: [{
|
|
144
|
+
type: Input
|
|
145
|
+
}], class: [{
|
|
146
|
+
type: Input
|
|
147
|
+
}], openChange: [{
|
|
148
|
+
type: Output
|
|
149
|
+
}] } });
|
|
150
|
+
/** Toggle for a `tolle-sources`, labelled with how many sources there are. */
|
|
151
|
+
export class SourcesTriggerComponent {
|
|
152
|
+
/**
|
|
153
|
+
* Angular writes a bound `class` input through its styling path, which does
|
|
154
|
+
* not mark an OnPush component dirty — without this hook the component keeps
|
|
155
|
+
* rendering the class it was born with.
|
|
156
|
+
*/
|
|
157
|
+
ngOnChanges() {
|
|
158
|
+
this.cdr.markForCheck();
|
|
159
|
+
}
|
|
160
|
+
/** Overrides the counted number of sources. @default null */
|
|
161
|
+
count = null;
|
|
162
|
+
/** Extra Tailwind classes merged onto the trigger via `cn()` (last-wins). */
|
|
163
|
+
class = '';
|
|
164
|
+
service = inject(SourcesService);
|
|
165
|
+
cdr = inject(ChangeDetectorRef);
|
|
166
|
+
subscriptions = new Subscription();
|
|
167
|
+
open = false;
|
|
168
|
+
registered = 0;
|
|
169
|
+
ngOnInit() {
|
|
170
|
+
this.subscriptions.add(this.service.open$.subscribe((open) => {
|
|
171
|
+
this.open = open;
|
|
172
|
+
this.cdr.markForCheck();
|
|
173
|
+
}));
|
|
174
|
+
this.subscriptions.add(this.service.ids$.subscribe((ids) => {
|
|
175
|
+
this.registered = ids.length;
|
|
176
|
+
this.cdr.markForCheck();
|
|
177
|
+
}));
|
|
178
|
+
}
|
|
179
|
+
ngOnDestroy() {
|
|
180
|
+
this.subscriptions.unsubscribe();
|
|
181
|
+
}
|
|
182
|
+
/** How many sources the trigger reports. */
|
|
183
|
+
get total() {
|
|
184
|
+
return this.count ?? this.registered;
|
|
185
|
+
}
|
|
186
|
+
get label() {
|
|
187
|
+
return 'Used ' + this.total + (this.total === 1 ? ' source' : ' sources');
|
|
188
|
+
}
|
|
189
|
+
get computedClass() {
|
|
190
|
+
return cn('flex w-fit items-center gap-1.5 rounded-md px-1.5 py-1 text-sm text-muted-foreground transition-colors', 'hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', this.class);
|
|
191
|
+
}
|
|
192
|
+
onToggle() {
|
|
193
|
+
this.service.toggle();
|
|
194
|
+
}
|
|
195
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SourcesTriggerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
196
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: SourcesTriggerComponent, isStandalone: true, selector: "tolle-sources-trigger", inputs: { count: "count", class: "class" }, usesOnChanges: true, ngImport: i0, template: `
|
|
197
|
+
<button
|
|
198
|
+
type="button"
|
|
199
|
+
data-sources-trigger
|
|
200
|
+
[attr.aria-expanded]="open"
|
|
201
|
+
[attr.data-state]="open ? 'open' : 'closed'"
|
|
202
|
+
[class]="computedClass"
|
|
203
|
+
(click)="onToggle()"
|
|
204
|
+
>
|
|
205
|
+
<i class="ri-links-line" aria-hidden="true"></i>
|
|
206
|
+
|
|
207
|
+
<span data-sources-label>{{ label }}</span>
|
|
208
|
+
|
|
209
|
+
<i
|
|
210
|
+
class="ri-arrow-down-s-line transition-transform duration-200"
|
|
211
|
+
[class.rotate-180]="open"
|
|
212
|
+
aria-hidden="true"
|
|
213
|
+
></i>
|
|
214
|
+
|
|
215
|
+
<ng-content></ng-content>
|
|
216
|
+
</button>
|
|
217
|
+
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
218
|
+
}
|
|
219
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SourcesTriggerComponent, decorators: [{
|
|
220
|
+
type: Component,
|
|
221
|
+
args: [{ selector: 'tolle-sources-trigger', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
222
|
+
<button
|
|
223
|
+
type="button"
|
|
224
|
+
data-sources-trigger
|
|
225
|
+
[attr.aria-expanded]="open"
|
|
226
|
+
[attr.data-state]="open ? 'open' : 'closed'"
|
|
227
|
+
[class]="computedClass"
|
|
228
|
+
(click)="onToggle()"
|
|
229
|
+
>
|
|
230
|
+
<i class="ri-links-line" aria-hidden="true"></i>
|
|
231
|
+
|
|
232
|
+
<span data-sources-label>{{ label }}</span>
|
|
233
|
+
|
|
234
|
+
<i
|
|
235
|
+
class="ri-arrow-down-s-line transition-transform duration-200"
|
|
236
|
+
[class.rotate-180]="open"
|
|
237
|
+
aria-hidden="true"
|
|
238
|
+
></i>
|
|
239
|
+
|
|
240
|
+
<ng-content></ng-content>
|
|
241
|
+
</button>
|
|
242
|
+
`, styles: [":host{display:block}\n"] }]
|
|
243
|
+
}], propDecorators: { count: [{
|
|
244
|
+
type: Input
|
|
245
|
+
}], class: [{
|
|
246
|
+
type: Input
|
|
247
|
+
}] } });
|
|
248
|
+
/**
|
|
249
|
+
* Holds the `tolle-source` entries of a `tolle-sources`.
|
|
250
|
+
*
|
|
251
|
+
* Stays in the DOM while collapsed — hidden and `inert` rather than removed —
|
|
252
|
+
* so the sources inside it stay registered and the trigger's count is right
|
|
253
|
+
* before the list has ever been opened.
|
|
254
|
+
*/
|
|
255
|
+
export class SourcesContentComponent {
|
|
256
|
+
/**
|
|
257
|
+
* Angular writes a bound `class` input through its styling path, which does
|
|
258
|
+
* not mark an OnPush component dirty — without this hook the component keeps
|
|
259
|
+
* rendering the class it was born with.
|
|
260
|
+
*/
|
|
261
|
+
ngOnChanges() {
|
|
262
|
+
this.cdr.markForCheck();
|
|
263
|
+
}
|
|
264
|
+
/** Extra Tailwind classes merged onto the content via `cn()` (last-wins). */
|
|
265
|
+
class = '';
|
|
266
|
+
service = inject(SourcesService);
|
|
267
|
+
cdr = inject(ChangeDetectorRef);
|
|
268
|
+
subscriptions = new Subscription();
|
|
269
|
+
open = false;
|
|
270
|
+
ngOnInit() {
|
|
271
|
+
this.subscriptions.add(this.service.open$.subscribe((open) => {
|
|
272
|
+
this.open = open;
|
|
273
|
+
this.cdr.markForCheck();
|
|
274
|
+
}));
|
|
275
|
+
}
|
|
276
|
+
ngOnDestroy() {
|
|
277
|
+
this.subscriptions.unsubscribe();
|
|
278
|
+
}
|
|
279
|
+
get computedClass() {
|
|
280
|
+
return cn('flex flex-col gap-1.5', !this.open && 'hidden', this.class);
|
|
281
|
+
}
|
|
282
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SourcesContentComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
283
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: SourcesContentComponent, isStandalone: true, selector: "tolle-sources-content", inputs: { class: "class" }, usesOnChanges: true, ngImport: i0, template: `
|
|
284
|
+
<div
|
|
285
|
+
data-sources-content
|
|
286
|
+
[attr.data-state]="open ? 'open' : 'closed'"
|
|
287
|
+
[attr.inert]="open ? null : ''"
|
|
288
|
+
[attr.aria-hidden]="open ? null : 'true'"
|
|
289
|
+
[class]="computedClass"
|
|
290
|
+
>
|
|
291
|
+
<ng-content></ng-content>
|
|
292
|
+
</div>
|
|
293
|
+
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
294
|
+
}
|
|
295
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SourcesContentComponent, decorators: [{
|
|
296
|
+
type: Component,
|
|
297
|
+
args: [{ selector: 'tolle-sources-content', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
298
|
+
<div
|
|
299
|
+
data-sources-content
|
|
300
|
+
[attr.data-state]="open ? 'open' : 'closed'"
|
|
301
|
+
[attr.inert]="open ? null : ''"
|
|
302
|
+
[attr.aria-hidden]="open ? null : 'true'"
|
|
303
|
+
[class]="computedClass"
|
|
304
|
+
>
|
|
305
|
+
<ng-content></ng-content>
|
|
306
|
+
</div>
|
|
307
|
+
`, styles: [":host{display:block}\n"] }]
|
|
308
|
+
}], propDecorators: { class: [{
|
|
309
|
+
type: Input
|
|
310
|
+
}] } });
|
|
311
|
+
const sourceVariants = cva('group flex items-center gap-2 rounded-md px-2 py-1.5 transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', {
|
|
312
|
+
variants: {
|
|
313
|
+
size: {
|
|
314
|
+
sm: 'text-xs',
|
|
315
|
+
default: 'text-sm',
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
defaultVariants: {
|
|
319
|
+
size: 'default',
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
/** A single citation inside a `tolle-sources-content`. */
|
|
323
|
+
export class SourceComponent {
|
|
324
|
+
/**
|
|
325
|
+
* Angular writes a bound `class` input through its styling path, which does
|
|
326
|
+
* not mark an OnPush component dirty — without this hook the component keeps
|
|
327
|
+
* rendering the class it was born with.
|
|
328
|
+
*/
|
|
329
|
+
ngOnChanges() {
|
|
330
|
+
this.cdr.markForCheck();
|
|
331
|
+
}
|
|
332
|
+
/** URL the citation points at. @default '' */
|
|
333
|
+
href = '';
|
|
334
|
+
/** Human-readable title; falls back to the href when empty. @default '' */
|
|
335
|
+
title = '';
|
|
336
|
+
/** URL of a favicon shown instead of the numbered chip. @default '' */
|
|
337
|
+
favicon = '';
|
|
338
|
+
/** Overrides the auto-numbered position chip. @default null */
|
|
339
|
+
index = null;
|
|
340
|
+
/** Text scale of the citation. @default 'default' */
|
|
341
|
+
size = 'default';
|
|
342
|
+
/** Extra Tailwind classes merged onto the citation via `cn()` (last-wins). */
|
|
343
|
+
class = '';
|
|
344
|
+
service = inject(SourcesService);
|
|
345
|
+
cdr = inject(ChangeDetectorRef);
|
|
346
|
+
subscriptions = new Subscription();
|
|
347
|
+
id = 'source-' + sourceId++;
|
|
348
|
+
order = 0;
|
|
349
|
+
ngOnInit() {
|
|
350
|
+
this.service.register(this.id);
|
|
351
|
+
this.subscriptions.add(this.service.ids$.subscribe(() => {
|
|
352
|
+
this.order = this.service.indexOf(this.id);
|
|
353
|
+
this.cdr.markForCheck();
|
|
354
|
+
}));
|
|
355
|
+
}
|
|
356
|
+
ngOnDestroy() {
|
|
357
|
+
this.service.unregister(this.id);
|
|
358
|
+
this.subscriptions.unsubscribe();
|
|
359
|
+
}
|
|
360
|
+
/** One-based number shown in the chip. */
|
|
361
|
+
get position() {
|
|
362
|
+
return this.index ?? this.order + 1;
|
|
363
|
+
}
|
|
364
|
+
get computedClass() {
|
|
365
|
+
return cn(sourceVariants({ size: this.size }), this.class);
|
|
366
|
+
}
|
|
367
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SourceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
368
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: SourceComponent, isStandalone: true, selector: "tolle-source", inputs: { href: "href", title: "title", favicon: "favicon", index: "index", size: "size", class: "class" }, usesOnChanges: true, ngImport: i0, template: `
|
|
369
|
+
<a
|
|
370
|
+
data-source
|
|
371
|
+
[attr.href]="href || null"
|
|
372
|
+
target="_blank"
|
|
373
|
+
rel="noreferrer noopener"
|
|
374
|
+
[class]="computedClass"
|
|
375
|
+
>
|
|
376
|
+
<img
|
|
377
|
+
*ngIf="favicon; else chip"
|
|
378
|
+
[attr.src]="favicon"
|
|
379
|
+
alt=""
|
|
380
|
+
aria-hidden="true"
|
|
381
|
+
class="size-4 shrink-0 rounded-sm"
|
|
382
|
+
/>
|
|
383
|
+
|
|
384
|
+
<ng-template #chip>
|
|
385
|
+
<span
|
|
386
|
+
class="flex size-4 shrink-0 items-center justify-center rounded-sm bg-muted text-[10px] font-medium text-muted-foreground"
|
|
387
|
+
aria-hidden="true"
|
|
388
|
+
>{{ position }}</span
|
|
389
|
+
>
|
|
390
|
+
</ng-template>
|
|
391
|
+
|
|
392
|
+
<span class="truncate text-foreground" data-source-title>{{ title || href }}</span>
|
|
393
|
+
|
|
394
|
+
<i
|
|
395
|
+
class="ri-external-link-line ml-auto shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100"
|
|
396
|
+
aria-hidden="true"
|
|
397
|
+
></i>
|
|
398
|
+
|
|
399
|
+
<ng-content></ng-content>
|
|
400
|
+
</a>
|
|
401
|
+
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
402
|
+
}
|
|
403
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SourceComponent, decorators: [{
|
|
404
|
+
type: Component,
|
|
405
|
+
args: [{ selector: 'tolle-source', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
406
|
+
<a
|
|
407
|
+
data-source
|
|
408
|
+
[attr.href]="href || null"
|
|
409
|
+
target="_blank"
|
|
410
|
+
rel="noreferrer noopener"
|
|
411
|
+
[class]="computedClass"
|
|
412
|
+
>
|
|
413
|
+
<img
|
|
414
|
+
*ngIf="favicon; else chip"
|
|
415
|
+
[attr.src]="favicon"
|
|
416
|
+
alt=""
|
|
417
|
+
aria-hidden="true"
|
|
418
|
+
class="size-4 shrink-0 rounded-sm"
|
|
419
|
+
/>
|
|
420
|
+
|
|
421
|
+
<ng-template #chip>
|
|
422
|
+
<span
|
|
423
|
+
class="flex size-4 shrink-0 items-center justify-center rounded-sm bg-muted text-[10px] font-medium text-muted-foreground"
|
|
424
|
+
aria-hidden="true"
|
|
425
|
+
>{{ position }}</span
|
|
426
|
+
>
|
|
427
|
+
</ng-template>
|
|
428
|
+
|
|
429
|
+
<span class="truncate text-foreground" data-source-title>{{ title || href }}</span>
|
|
430
|
+
|
|
431
|
+
<i
|
|
432
|
+
class="ri-external-link-line ml-auto shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100"
|
|
433
|
+
aria-hidden="true"
|
|
434
|
+
></i>
|
|
435
|
+
|
|
436
|
+
<ng-content></ng-content>
|
|
437
|
+
</a>
|
|
438
|
+
`, styles: [":host{display:block}\n"] }]
|
|
439
|
+
}], propDecorators: { href: [{
|
|
440
|
+
type: Input
|
|
441
|
+
}], title: [{
|
|
442
|
+
type: Input
|
|
443
|
+
}], favicon: [{
|
|
444
|
+
type: Input
|
|
445
|
+
}], index: [{
|
|
446
|
+
type: Input
|
|
447
|
+
}], size: [{
|
|
448
|
+
type: Input
|
|
449
|
+
}], class: [{
|
|
450
|
+
type: Input
|
|
451
|
+
}] } });
|
|
452
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic291cmNlcy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy90b2xsZS9zcmMvbGliL3NvdXJjZXMuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQWdDLE1BQU0sRUFBaUIsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3BMLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNyRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDdEMsT0FBTyxFQUFFLEdBQUcsRUFBcUIsTUFBTSwwQkFBMEIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sWUFBWSxDQUFDOzs7QUFFaEMsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDO0FBRWpCOzs7Ozs7OztHQVFHO0FBRUgsTUFBTSxPQUFPLGNBQWM7SUFDUixVQUFVLEdBQUcsSUFBSSxlQUFlLENBQVUsS0FBSyxDQUFDLENBQUM7SUFDbEUsbURBQW1EO0lBQzFDLEtBQUssR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBRS9CLFNBQVMsR0FBRyxJQUFJLGVBQWUsQ0FBVyxFQUFFLENBQUMsQ0FBQztJQUMvRCw0RUFBNEU7SUFDbkUsSUFBSSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxFQUFFLENBQUM7SUFFOUMsZ0RBQWdEO0lBQ2hELElBQUksSUFBSTtRQUNOLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUM7SUFDL0IsQ0FBQztJQUVELGlEQUFpRDtJQUNqRCxJQUFJLEtBQUs7UUFDUCxPQUFPLElB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QWE7UUFDZixPQUFPLEVBQUUsQ0FBQyxjQUFjLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzdELENBQUM7d0dBdERVLGVBQWU7NEZBQWYsZUFBZSx5TUFuQ2hCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQ1QsK0ZBbkNTLFlBQVk7OzRGQXFDWCxlQUFlO2tCQXpDM0IsU0FBUzsrQkFDRSxjQUFjLGNBRVosSUFBSSxXQUNQLENBQUMsWUFBWSxDQUFDLG1CQUNOLHVCQUF1QixDQUFDLE1BQU0sWUFDckM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWlDVDs4QkFjUSxJQUFJO3NCQUFaLEtBQUs7Z0JBRUcsS0FBSztzQkFBYixLQUFLO2dCQUVHLE9BQU87c0JBQWYsS0FBSztnQkFFRyxLQUFLO3NCQUFiLEtBQUs7Z0JBRUcsSUFBSTtzQkFBWixLQUFLO2dCQUVHLEtBQUs7c0JBQWIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBFdmVudEVtaXR0ZXIsIEluamVjdGFibGUsIElucHV0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSwgT25Jbml0LCBPdXRwdXQsIFNpbXBsZUNoYW5nZXMsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBza2lwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgY3ZhLCB0eXBlIFZhcmlhbnRQcm9wcyB9IGZyb20gJ2NsYXNzLXZhcmlhbmNlLWF1dGhvcml0eSc7XG5pbXBvcnQgeyBjbiB9IGZyb20gJy4vdXRpbHMvY24nO1xuXG5sZXQgc291cmNlSWQgPSAwO1xuXG4vKipcbiAqIENvb3JkaW5hdGVzIGEgYHRvbGxlLXNvdXJjZXNgIHdpdGggaXRzIHRyaWdnZXIsIGNvbnRlbnQgYW5kIHNvdXJjZXMuXG4gKlxuICogVGhlIHRyaWdnZXIgaGFzIHRvIHJlcG9ydCBob3cgbWFueSBzb3VyY2VzIHdlcmUgcHJvamVjdGVkIGludG8gYSBzaWJsaW5nXG4gKiBjb21wb25lbnQsIHNvIGV2ZXJ5IGB0b2xsZS1zb3VyY2VgIHJlZ2lzdGVycyBoZXJlIGFuZCB0aGUgdHJpZ2dlciByZW5kZXJzXG4gKiBmcm9tIHRoZSByZXN1bHRpbmcgY291bnQuXG4gKlxuICogUHJvdmlkZWQgb24gYFNvdXJjZXNDb21wb25lbnRgLCBzbyBlYWNoIGNpdGF0aW9uIGxpc3QgZ2V0cyBpdHMgb3duIGluc3RhbmNlLlxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgU291cmNlc1NlcnZpY2Uge1xuICBwcml2YXRlIHJlYWRvbmx5IG9wZW5Tb3VyY2UgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgLyoqIEVtaXRzIHdoZXRoZXIgdGhlIGNpdGF0aW9uIGxpc3QgaXMgZXhwYW5kZWQuICovXG4gIHJlYWRvbmx5IG9wZW4kID0gdGhpcy5vcGVuU291cmNlLmFzT2JzZXJ2YWJsZSgpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgaWRzU291cmNlID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmdbXT4oW10pO1xuICAvKiogRW1pdHMgdGhlIGlkcyBvZiB0aGUgcmVnaXN0ZXJlZCBzb3VyY2VzLCBpbiByZWdpc3RyYXRpb24gKERPTSkgb3JkZXIuICovXG4gIHJlYWRvbmx5IGlkcyQgPSB0aGlzLmlkc1NvdXJjZS5hc09ic2VydmFibGUoKTtcblxuICAvKiogVHJ1ZSB3aGlsZSB0aGUgY2l0YXRpb24gbGlzdCBpcyBleHBhbmRlZC4gKi9cbiAgZ2V0IG9wZW4oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMub3BlblNvdXJjZS52YWx1ZTtcbiAgfVxuXG4gIC8qKiBIb3cgbWFueSBzb3VyY2VzIGFyZSBjdXJyZW50bHkgcmVnaXN0ZXJlZC4gKi9cbiAgZ2V0IGNvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuaWRzU291cmNlLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIHNldE9wZW4odmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5vcGVuU291cmNlLnZhbHVlICE9PSB2YWx1ZSkgdGhpcy5vcGVuU291cmNlLm5leHQodmFsdWUpO1xuICB9XG5cbiAgdG9nZ2xlKCk6IHZvaWQge1xuICAgIHRoaXMuc2V0T3BlbighdGhpcy5vcGVuU291cmNlLnZhbHVlKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKGlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pZHNTb3VyY2UudmFsdWUuaW5jbHVkZXMoaWQpKSByZXR1cm47XG4gICAgdGhpcy5pZHNTb3VyY2UubmV4dChbLi4udGhpcy5pZHNTb3VyY2UudmFsdWUsIGlkXSk7XG4gIH1cblxuICB1bnJlZ2lzdGVyKGlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmlkc1NvdXJjZS5uZXh0KHRoaXMuaWRzU291cmNlLnZhbHVlLmZpbHRlcigoZXhpc3RpbmcpID0+IGV4aXN0aW5nICE9PSBpZCkpO1xuICB9XG5cbiAgLyoqIFplcm8tYmFzZWQgcG9zaXRpb24gb2YgYSBzb3VyY2UsIG9yIC0xIHdoZW4gaXQgaXMgbm90IHJlZ2lzdGVyZWQuICovXG4gIGluZGV4T2YoaWQ6IHN0cmluZyk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuaWRzU291cmNlLnZhbHVlLmluZGV4T2YoaWQpO1xuICB9XG59XG5cbmNvbnN0IHNvdXJjZXNWYXJpYW50cyA9IGN2YSgnZmxleCB3LWZ1bGwgZmxleC1jb2wgZ2FwLTIgdGV4dC1zbScsIHtcbiAgdmFyaWFudHM6IHtcbiAgICB2YXJpYW50OiB7XG4gICAgICBkZWZhdWx0OiAnJyxcbiAgICAgIGNhcmQ6ICdyb3VuZGVkLW1kIGJvcmRlciBib3JkZXItYm9yZGVyIGJnLWNhcmQgcC0zIHRleHQtY2FyZC1mb3JlZ3JvdW5kJyxcbiAgICAgIG11dGVkOiAncm91bmRlZC1tZCBiZy1tdXRlZCBwLTMnLFxuICAgIH0sXG4gIH0sXG4gIGRlZmF1bHRWYXJpYW50czoge1xuICAgIHZhcmlhbnQ6ICdkZWZhdWx0JyxcbiAgfSxcbn0pO1xuXG5leHBvcnQgdHlwZSBTb3VyY2VzUHJvcHMgPSBWYXJpYW50UHJvcHM8dHlwZW9mIHNvdXJjZXNWYXJpYW50cz47XG5cbi8qKlxuICogQSBjb2xsYXBzaWJsZSBsaXN0IG9mIHRoZSBjaXRhdGlvbnMgYmVoaW5kIGEgcmVzcG9uc2UuXG4gKlxuICogQ29tcG9zZSBpdCBmcm9tIGB0b2xsZS1zb3VyY2VzLXRyaWdnZXJgLCBgdG9sbGUtc291cmNlcy1jb250ZW50YCBhbmQgb25lXG4gKiBgdG9sbGUtc291cmNlYCBwZXIgY2l0YXRpb24g4oCUIHRoZSB0cmlnZ2VyIGNvdW50cyB0aGUgc291cmNlcyBmb3IgeW91LlxuICogQG5ld1xuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0b2xsZS1zb3VyY2VzJyxcbiAgc3R5bGVzOiBbJzpob3N0IHsgZGlzcGxheTogYmxvY2s7IH0nXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIHByb3ZpZGVyczogW1NvdXJjZXNTZXJ2aWNlXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBbY2xhc3NdPVwiY29tcHV0ZWRDbGFzc1wiIFthdHRyLmRhdGEtc3RhdGVdPVwib3BlbiA/ICdvcGVuJyA6ICdjbG9zZWQnXCI+XG4gICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIFNvdXJjZXNDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcbiAgLyoqIFdoZXRoZXIgdGhlIGNpdGF0aW9uIGxpc3QgaXMgZXhwYW5kZWQuIEBkZWZhdWx0IGZhbHNlICovXG4gIEBJbnB1dCgpIG9wZW4gPSBmYWxzZTtcbiAgLyoqIFZpc3VhbCB0cmVhdG1lbnQgb2YgdGhlIGxpc3QgY29udGFpbmVyLiBAZGVmYXVsdCAnZGVmYXVsdCcgKi9cbiAgQElucHV0KCkgdmFyaWFudDogU291cmNlc1Byb3BzWyd2YXJpYW50J10gPSAnZGVmYXVsdCc7XG4gIC8qKiBFeHRyYSBUYWlsd2luZCBjbGFzc2VzIG1lcmdlZCBvbnRvIHRoZSBsaXN0IHZpYSBgY24oKWAgKGxhc3Qtd2lucykuICovXG4gIEBJbnB1dCgpIGNsYXNzID0gJyc7XG5cbiAgLyoqIEVtaXR0ZWQgd2l0aCB0aGUgbmV3IHN0YXRlIHdoZW5ldmVyIHRoZSBsaXN0IGlzIGV4cGFuZGVkIG9yIGNvbGxhcHNlZC4gKi9cbiAgQE91dHB1dCgpIG9wZW5DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBzZXJ2aWNlID0gaW5qZWN0KFNvdXJjZXNTZXJ2aWNlKTtcbiAgcHJpdmF0ZSByZWFkb25seSBjZHIgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuICBwcml2YXRlIHJlYWRvbmx5IHN1YnNjcmlwdGlvbnMgPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gIC8qKiBUcnVlIHdoaWxlIGFuIGBvcGVuYCBpbnB1dCBpcyBiZWluZyBwdXNoZWQgaW50byB0aGUgc2VydmljZS4gKi9cbiAgcHJpdmF0ZSBhcHBseWluZ0lucHV0ID0gZmFsc2U7XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zZXJ2aWNlLnNldE9wZW4odGhpcy5vcGVuKTtcbiAgICAvLyBgc2tpcCgxKWAgZHJvcHMgdGhlIEJlaGF2aW9yU3ViamVjdCdzIGN1cnJlbnQgdmFsdWUgc28gbW91bnRpbmcgbmV2ZXJcbiAgICAvLyBlbWl0cyBhIHNwdXJpb3VzIGBvcGVuQ2hhbmdlYC5cbiAgICB0aGlzLnN1YnNjcmlwdGlvbnMuYWRkKFxuICAgICAgdGhpcy5zZXJ2aWNlLm9wZW4kLnBpcGUoc2tpcCgxKSkuc3Vic2NyaWJlKChvcGVuKSA9PiB7XG4gICAgICAgIHRoaXMub3BlbiA9IG9wZW47XG4gICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgICAgICAvLyBPbmx5IHVzZXItZHJpdmVuIHRvZ2dsZXMgYXJlIHdvcnRoIHJlcG9ydGluZzsgZWNob2luZyBhIGNoYW5nZSB0aGVcbiAgICAgICAgLy8gcGFyZW50IGp1c3QgbWFkZSB3b3VsZCBmaWdodCBhIGBbKG9wZW4pXWAgYmluZGluZy5cbiAgICAgICAgaWYgKCF0aGlzLmFwcGx5aW5nSW5wdXQpIHRoaXMub3BlbkNoYW5nZS5lbWl0KG9wZW4pO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzWydvcGVuJ10pIHRoaXMuYXBwbHlJbnB1dCh0aGlzLm9wZW4pO1xuICBcbiAgICAvLyBBIGJvdW5kIGBjbGFzc2AgaW5wdXQgaXMgd3JpdHRlbiB0aHJvdWdoIEFuZ3VsYXIncyBzdHlsaW5nIHBhdGgsXG4gICAgLy8gd2hpY2ggZG9lcyBub3QgbWFyayBhbiBPblB1c2ggdmlldyBkaXJ0eSBvbiBpdHMgb3duLlxuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgcHJpdmF0ZSBhcHBseUlucHV0KG9wZW46IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmFwcGx5aW5nSW5wdXQgPSB0cnVlO1xuICAgIHRyeSB7XG4gICAgICB0aGlzLnNlcnZpY2Uuc2V0T3BlbihvcGVuKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5hcHBseWluZ0lucHV0ID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBnZXQgY29tcHV0ZWRDbGFzcygpIHtcbiAgICByZXR1cm4gY24oc291cmNlc1ZhcmlhbnRzKHsgdmFyaWFudDogdGhpcy52YXJpYW50IH0pLCB0aGlzLmNsYXNzKTtcbiAgfVxufVxuXG4vKiogVG9nZ2xlIGZvciBhIGB0b2xsZS1zb3VyY2VzYCwgbGFiZWxsZWQgd2l0aCBob3cgbWFueSBzb3VyY2VzIHRoZXJlIGFyZS4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3RvbGxlLXNvdXJjZXMtdHJpZ2dlcicsXG4gIHN0eWxlczogWyc6aG9zdCB7IGRpc3BsYXk6IGJsb2NrOyB9J10sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGU6IGBcbiAgICA8YnV0dG9uXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgIGRhdGEtc291cmNlcy10cmlnZ2VyXG4gICAgICBbYXR0ci5hcmlhLWV4cGFuZGVkXT1cIm9wZW5cIlxuICAgICAgW2F0dHIuZGF0YS1zdGF0ZV09XCJvcGVuID8gJ29wZW4nIDogJ2Nsb3NlZCdcIlxuICAgICAgW2NsYXNzXT1cImNvbXB1dGVkQ2xhc3NcIlxuICAgICAgKGNsaWNrKT1cIm9uVG9nZ2xlKClcIlxuICAgID5cbiAgICAgIDxpIGNsYXNzPVwicmktbGlua3MtbGluZVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPjwvaT5cblxuICAgICAgPHNwYW4gZGF0YS1zb3VyY2VzLWxhYmVsPnt7IGxhYmVsIH19PC9zcGFuPlxuXG4gICAgICA8aVxuICAgICAgICBjbGFzcz1cInJpLWFycm93LWRvd24tcy1saW5lIHRyYW5zaXRpb24tdHJhbnNmb3JtIGR1cmF0aW9uLTIwMFwiXG4gICAgICAgIFtjbGFzcy5yb3RhdGUtMTgwXT1cIm9wZW5cIlxuICAgICAgICBhcmlhLWhpZGRlbj1cInRydWVcIlxuICAgICAgPjwvaT5cblxuICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICAgIDwvYnV0dG9uPlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBTb3VyY2VzVHJpZ2dlckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgT25Jbml0LCBPbkRlc3Ryb3kge1xuXG4gIC8qKlxuICAgKiBBbmd1bGFyIHdyaXRlcyBhIGJvdW5kIGBjbGFzc2AgaW5wdXQgdGhyb3VnaCBpdHMgc3R5bGluZyBwYXRoLCB3aGljaCBkb2VzXG4gICAqIG5vdCBtYXJrIGFuIE9uUHVzaCBjb21wb25lbnQgZGlydHkg4oCUIHdpdGhvdXQgdGhpcyBob29rIHRoZSBjb21wb25lbnQga2VlcHNcbiAgICogcmVuZGVyaW5nIHRoZSBjbGFzcyBpdCB3YXMgYm9ybiB3aXRoLlxuICAgKi9cbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKiogT3ZlcnJpZGVzIHRoZSBjb3VudGVkIG51bWJlciBvZiBzb3VyY2VzLiBAZGVmYXVsdCBudWxsICovXG4gIEBJbnB1dCgpIGNvdW50OiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqIEV4dHJhIFRhaWx3aW5kIGNsYXNzZXMgbWVyZ2VkIG9udG8gdGhlIHRyaWdnZXIgdmlhIGBjbigpYCAobGFzdC13aW5zKS4gKi9cbiAgQElucHV0KCkgY2xhc3MgPSAnJztcblxuICBwcml2YXRlIHJlYWRvbmx5IHNlcnZpY2UgPSBpbmplY3QoU291cmNlc1NlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3Vic2NyaXB0aW9ucyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICBvcGVuID0gZmFsc2U7XG4gIHJlZ2lzdGVyZWQgPSAwO1xuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5hZGQoXG4gICAgICB0aGlzLnNlcnZpY2Uub3BlbiQuc3Vic2NyaWJlKChvcGVuKSA9PiB7XG4gICAgICAgIHRoaXMub3BlbiA9IG9wZW47XG4gICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgICAgfSlcbiAgICApO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5hZGQoXG4gICAgICB0aGlzLnNlcnZpY2UuaWRzJC5zdWJzY3JpYmUoKGlkcykgPT4ge1xuICAgICAgICB0aGlzLnJlZ2lzdGVyZWQgPSBpZHMubGVuZ3RoO1xuICAgICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy51bnN1YnNjcmliZSgpO1xuICB9XG5cbiAgLyoqIEhvdyBtYW55IHNvdXJjZXMgdGhlIHRyaWdnZXIgcmVwb3J0cy4gKi9cbiAgZ2V0IHRvdGFsKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuY291bnQgPz8gdGhpcy5yZWdpc3RlcmVkO1xuICB9XG5cbiAgZ2V0IGxhYmVsKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICdVc2VkICcgKyB0aGlzLnRvdGFsICsgKHRoaXMudG90YWwgPT09IDEgPyAnIHNvdXJjZScgOiAnIHNvdXJjZXMnKTtcbiAgfVxuXG4gIGdldCBjb21wdXRlZENsYXNzKCkge1xuICAgIHJldHVybiBjbihcbiAgICAgICdmbGV4IHctZml0IGl0ZW1zLWNlbnRlciBnYXAtMS41IHJvdW5kZWQtbWQgcHgtMS41IHB5LTEgdGV4dC1zbSB0ZXh0LW11dGVkLWZvcmVncm91bmQgdHJhbnNpdGlvbi1jb2xvcnMnLFxuICAgICAgJ2hvdmVyOnRleHQtZm9yZWdyb3VuZCBmb2N1cy12aXNpYmxlOm91dGxpbmUtbm9uZSBmb2N1cy12aXNpYmxlOnJpbmctMiBmb2N1cy12aXNpYmxlOnJpbmctcmluZycsXG4gICAgICB0aGlzLmNsYXNzXG4gICAgKTtcbiAgfVxuXG4gIG9uVG9nZ2xlKCk6IHZvaWQge1xuICAgIHRoaXMuc2VydmljZS50b2dnbGUoKTtcbiAgfVxufVxuXG4vKipcbiAqIEhvbGRzIHRoZSBgdG9sbGUtc291cmNlYCBlbnRyaWVzIG9mIGEgYHRvbGxlLXNvdXJjZXNgLlxuICpcbiAqIFN0YXlzIGluIHRoZSBET00gd2hpbGUgY29sbGFwc2VkIOKAlCBoaWRkZW4gYW5kIGBpbmVydGAgcmF0aGVyIHRoYW4gcmVtb3ZlZCDigJRcbiAqIHNvIHRoZSBzb3VyY2VzIGluc2lkZSBpdCBzdGF5IHJlZ2lzdGVyZWQgYW5kIHRoZSB0cmlnZ2VyJ3MgY291bnQgaXMgcmlnaHRcbiAqIGJlZm9yZSB0aGUgbGlzdCBoYXMgZXZlciBiZWVuIG9wZW5lZC5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9sbGUtc291cmNlcy1jb250ZW50JyxcbiAgc3R5bGVzOiBbJzpob3N0IHsgZGlzcGxheTogYmxvY2s7IH0nXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXZcbiAgICAgIGRhdGEtc291cmNlcy1jb250ZW50XG4gICAgICBbYXR0ci5kYXRhLXN0YXRlXT1cIm9wZW4gPyAnb3BlbicgOiAnY2xvc2VkJ1wiXG4gICAgICBbYXR0ci5pbmVydF09XCJvcGVuID8gbnVsbCA6ICcnXCJcbiAgICAgIFthdHRyLmFyaWEtaGlkZGVuXT1cIm9wZW4gPyBudWxsIDogJ3RydWUnXCJcbiAgICAgIFtjbGFzc109XCJjb21wdXRlZENsYXNzXCJcbiAgICA+XG4gICAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIFNvdXJjZXNDb250ZW50Q29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkluaXQsIE9uRGVzdHJveSB7XG5cbiAgLyoqXG4gICAqIEFuZ3VsYXIgd3JpdGVzIGEgYm91bmQgYGNsYXNzYCBpbnB1dCB0aHJvdWdoIGl0cyBzdHlsaW5nIHBhdGgsIHdoaWNoIGRvZXNcbiAgICogbm90IG1hcmsgYW4gT25QdXNoIGNvbXBvbmVudCBkaXJ0eSDigJQgd2l0aG91dCB0aGlzIGhvb2sgdGhlIGNvbXBvbmVudCBrZWVwc1xuICAgKiByZW5kZXJpbmcgdGhlIGNsYXNzIGl0IHdhcyBib3JuIHdpdGguXG4gICAqL1xuICBuZ09uQ2hhbmdlcygpOiB2b2lkIHtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIC8qKiBFeHRyYSBUYWlsd2luZCBjbGFzc2VzIG1lcmdlZCBvbnRvIHRoZSBjb250ZW50IHZpYSBgY24oKWAgKGxhc3Qtd2lucykuICovXG4gIEBJbnB1dCgpIGNsYXNzID0gJyc7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBzZXJ2aWNlID0gaW5qZWN0KFNvdXJjZXNTZXJ2aWNlKTtcbiAgcHJpdmF0ZSByZWFkb25seSBjZHIgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuICBwcml2YXRlIHJlYWRvbmx5IHN1YnNjcmlwdGlvbnMgPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG5cbiAgb3BlbiA9IGZhbHNlO1xuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5hZGQoXG4gICAgICB0aGlzLnNlcnZpY2Uub3BlbiQuc3Vic2NyaWJlKChvcGVuKSA9PiB7XG4gICAgICAgIHRoaXMub3BlbiA9IG9wZW47XG4gICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBnZXQgY29tcHV0ZWRDbGFzcygpIHtcbiAgICByZXR1cm4gY24oJ2ZsZXggZmxleC1jb2wgZ2FwLTEuNScsICF0aGlzLm9wZW4gJiYgJ2hpZGRlbicsIHRoaXMuY2xhc3MpO1xuICB9XG59XG5cbmNvbnN0IHNvdXJjZVZhcmlhbnRzID0gY3ZhKFxuICAnZ3JvdXAgZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTIgcm91bmRlZC1tZCBweC0yIHB5LTEuNSB0cmFuc2l0aW9uLWNvbG9ycyBob3ZlcjpiZy1hY2NlbnQgaG92ZXI6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCBmb2N1cy12aXNpYmxlOm91dGxpbmUtbm9uZSBmb2N1cy12aXNpYmxlOnJpbmctMiBmb2N1cy12aXNpYmxlOnJpbmctcmluZycsXG4gIHtcbiAgICB2YXJpYW50czoge1xuICAgICAgc2l6ZToge1xuICAgICAgICBzbTogJ3RleHQteHMnLFxuICAgICAgICBkZWZhdWx0OiAndGV4dC1zbScsXG4gICAgICB9LFxuICAgIH0sXG4gICAgZGVmYXVsdFZhcmlhbnRzOiB7XG4gICAgICBzaXplOiAnZGVmYXVsdCcsXG4gICAgfSxcbiAgfVxuKTtcblxuZXhwb3J0IHR5cGUgU291cmNlUHJvcHMgPSBWYXJpYW50UHJvcHM8dHlwZW9mIHNvdXJjZVZhcmlhbnRzPjtcblxuLyoqIEEgc2luZ2xlIGNpdGF0aW9uIGluc2lkZSBhIGB0b2xsZS1zb3VyY2VzLWNvbnRlbnRgLiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9sbGUtc291cmNlJyxcbiAgc3R5bGVzOiBbJzpob3N0IHsgZGlzcGxheTogYmxvY2s7IH0nXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxhXG4gICAgICBkYXRhLXNvdXJjZVxuICAgICAgW2F0dHIuaHJlZl09XCJocmVmIHx8IG51bGxcIlxuICAgICAgdGFyZ2V0PVwiX2JsYW5rXCJcbiAgICAgIHJlbD1cIm5vcmVmZXJyZXIgbm9vcGVuZXJcIlxuICAgICAgW2NsYXNzXT1cImNvbXB1dGVkQ2xhc3NcIlxuICAgID5cbiAgICAgIDxpbWdcbiAgICAgICAgKm5nSWY9XCJmYXZpY29uOyBlbHNlIGNoaXBcIlxuICAgICAgICBbYXR0ci5zcmNdPVwiZmF2aWNvblwiXG4gICAgICAgIGFsdD1cIlwiXG4gICAgICAgIGFyaWEtaGlkZGVuPVwidHJ1ZVwiXG4gICAgICAgIGNsYXNzPVwic2l6ZS00IHNocmluay0wIHJvdW5kZWQtc21cIlxuICAgICAgLz5cblxuICAgICAgPG5nLXRlbXBsYXRlICNjaGlwPlxuICAgICAgICA8c3BhblxuICAgICAgICAgIGNsYXNzPVwiZmxleCBzaXplLTQgc2hyaW5rLTAgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHJvdW5kZWQtc20gYmctbXV0ZWQgdGV4dC1bMTBweF0gZm9udC1tZWRpdW0gdGV4dC1tdXRlZC1mb3JlZ3JvdW5kXCJcbiAgICAgICAgICBhcmlhLWhpZGRlbj1cInRydWVcIlxuICAgICAgICAgID57eyBwb3NpdGlvbiB9fTwvc3BhblxuICAgICAgICA+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICA8c3BhbiBjbGFzcz1cInRydW5jYXRlIHRleHQtZm9yZWdyb3VuZFwiIGRhdGEtc291cmNlLXRpdGxlPnt7IHRpdGxlIHx8IGhyZWYgfX08L3NwYW4+XG5cbiAgICAgIDxpXG4gICAgICAgIGNsYXNzPVwicmktZXh0ZXJuYWwtbGluay1saW5lIG1sLWF1dG8gc2hyaW5rLTAgdGV4dC1tdXRlZC1mb3JlZ3JvdW5kIG9wYWNpdHktMCB0cmFuc2l0aW9uLW9wYWNpdHkgZ3JvdXAtaG92ZXI6b3BhY2l0eS0xMDBcIlxuICAgICAgICBhcmlhLWhpZGRlbj1cInRydWVcIlxuICAgICAgPjwvaT5cblxuICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICAgIDwvYT5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgU291cmNlQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkluaXQsIE9uRGVzdHJveSB7XG5cbiAgLyoqXG4gICAqIEFuZ3VsYXIgd3JpdGVzIGEgYm91bmQgYGNsYXNzYCBpbnB1dCB0aHJvdWdoIGl0cyBzdHlsaW5nIHBhdGgsIHdoaWNoIGRvZXNcbiAgICogbm90IG1hcmsgYW4gT25QdXNoIGNvbXBvbmVudCBkaXJ0eSDigJQgd2l0aG91dCB0aGlzIGhvb2sgdGhlIGNvbXBvbmVudCBrZWVwc1xuICAgKiByZW5kZXJpbmcgdGhlIGNsYXNzIGl0IHdhcyBib3JuIHdpdGguXG4gICAqL1xuICBuZ09uQ2hhbmdlcygpOiB2b2lkIHtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIC8qKiBVUkwgdGhlIGNpdGF0aW9uIHBvaW50cyBhdC4gQGRlZmF1bHQgJycgKi9cbiAgQElucHV0KCkgaHJlZiA9ICcnO1xuICAvKiogSHVtYW4tcmVhZGFibGUgdGl0bGU7IGZhbGxzIGJhY2sgdG8gdGhlIGhyZWYgd2hlbiBlbXB0eS4gQGRlZmF1bHQgJycgKi9cbiAgQElucHV0KCkgdGl0bGUgPSAnJztcbiAgLyoqIFVSTCBvZiBhIGZhdmljb24gc2hvd24gaW5zdGVhZCBvZiB0aGUgbnVtYmVyZWQgY2hpcC4gQGRlZmF1bHQgJycgKi9cbiAgQElucHV0KCkgZmF2aWNvbiA9ICcnO1xuICAvKiogT3ZlcnJpZGVzIHRoZSBhdXRvLW51bWJlcmVkIHBvc2l0aW9uIGNoaXAuIEBkZWZhdWx0IG51bGwgKi9cbiAgQElucHV0KCkgaW5kZXg6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICAvKiogVGV4dCBzY2FsZSBvZiB0aGUgY2l0YXRpb24uIEBkZWZhdWx0ICdkZWZhdWx0JyAqL1xuICBASW5wdXQoKSBzaXplOiBTb3VyY2VQcm9wc1snc2l6ZSddID0gJ2RlZmF1bHQnO1xuICAvKiogRXh0cmEgVGFpbHdpbmQgY2xhc3NlcyBtZXJnZWQgb250byB0aGUgY2l0YXRpb24gdmlhIGBjbigpYCAobGFzdC13aW5zKS4gKi9cbiAgQElucHV0KCkgY2xhc3MgPSAnJztcblxuICBwcml2YXRlIHJlYWRvbmx5IHNlcnZpY2UgPSBpbmplY3QoU291cmNlc1NlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG4gIHByaXZhdGUgcmVhZG9ubHkgc3Vic2NyaXB0aW9ucyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGlkID0gJ3NvdXJjZS0nICsgc291cmNlSWQrKztcblxuICBvcmRlciA9IDA7XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zZXJ2aWNlLnJlZ2lzdGVyKHRoaXMuaWQpO1xuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5hZGQoXG4gICAgICB0aGlzLnNlcnZpY2UuaWRzJC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLm9yZGVyID0gdGhpcy5zZXJ2aWNlLmluZGV4T2YodGhpcy5pZCk7XG4gICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5zZXJ2aWNlLnVucmVnaXN0ZXIodGhpcy5pZCk7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICAvKiogT25lLWJhc2VkIG51bWJlciBzaG93biBpbiB0aGUgY2hpcC4gKi9cbiAgZ2V0IHBvc2l0aW9uKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuaW5kZXggPz8gdGhpcy5vcmRlciArIDE7XG4gIH1cblxuICBnZXQgY29tcHV0ZWRDbGFzcygpIHtcbiAgICByZXR1cm4gY24oc291cmNlVmFyaWFudHMoeyBzaXplOiB0aGlzLnNpemUgfSksIHRoaXMuY2xhc3MpO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef, inject } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { cva } from 'class-variance-authority';
|
|
4
|
+
import { cn } from './utils/cn';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
const spinnerVariants = cva('inline-block animate-spin rounded-full border-solid border-current border-r-transparent align-[-0.125em]', {
|
|
7
|
+
variants: {
|
|
8
|
+
size: {
|
|
9
|
+
xs: 'h-3 w-3 border-[1.5px]',
|
|
10
|
+
sm: 'h-4 w-4 border-2',
|
|
11
|
+
default: 'h-5 w-5 border-2',
|
|
12
|
+
lg: 'h-8 w-8 border-[3px]',
|
|
13
|
+
xl: 'h-12 w-12 border-4',
|
|
14
|
+
},
|
|
15
|
+
variant: {
|
|
16
|
+
default: 'text-foreground',
|
|
17
|
+
primary: 'text-primary',
|
|
18
|
+
muted: 'text-muted-foreground',
|
|
19
|
+
destructive: 'text-destructive',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
defaultVariants: { size: 'default', variant: 'default' },
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* An indeterminate loading indicator. Renders as `role="status"` with a
|
|
26
|
+
* visually-hidden label so screen readers announce the loading state.
|
|
27
|
+
* @new
|
|
28
|
+
*/
|
|
29
|
+
export class SpinnerComponent {
|
|
30
|
+
cdr = inject(ChangeDetectorRef);
|
|
31
|
+
ngOnChanges() {
|
|
32
|
+
this.cdr.markForCheck();
|
|
33
|
+
}
|
|
34
|
+
/** Diameter of the spinner. @default 'default' */
|
|
35
|
+
size = 'default';
|
|
36
|
+
/** Colour of the spinner, inherited from the theme tokens. @default 'default' */
|
|
37
|
+
variant = 'default';
|
|
38
|
+
/** Accessible label announced while the spinner is visible. @default 'Loading' */
|
|
39
|
+
label = 'Loading';
|
|
40
|
+
/** Extra Tailwind classes merged onto the spinner via `cn()` (last-wins). */
|
|
41
|
+
class = '';
|
|
42
|
+
get computedClass() {
|
|
43
|
+
return cn(spinnerVariants({ size: this.size, variant: this.variant }), this.class);
|
|
44
|
+
}
|
|
45
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
46
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: SpinnerComponent, isStandalone: true, selector: "tolle-spinner", inputs: { size: "size", variant: "variant", label: "label", class: "class" }, usesOnChanges: true, ngImport: i0, template: `
|
|
47
|
+
<span role="status" [attr.aria-label]="label" [class]="computedClass">
|
|
48
|
+
<span class="sr-only">{{ label }}</span>
|
|
49
|
+
</span>
|
|
50
|
+
`, isInline: true, styles: [":host{display:inline-flex}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
51
|
+
}
|
|
52
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SpinnerComponent, decorators: [{
|
|
53
|
+
type: Component,
|
|
54
|
+
args: [{ selector: 'tolle-spinner', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
55
|
+
<span role="status" [attr.aria-label]="label" [class]="computedClass">
|
|
56
|
+
<span class="sr-only">{{ label }}</span>
|
|
57
|
+
</span>
|
|
58
|
+
`, styles: [":host{display:inline-flex}\n"] }]
|
|
59
|
+
}], propDecorators: { size: [{
|
|
60
|
+
type: Input
|
|
61
|
+
}], variant: [{
|
|
62
|
+
type: Input
|
|
63
|
+
}], label: [{
|
|
64
|
+
type: Input
|
|
65
|
+
}], class: [{
|
|
66
|
+
type: Input
|
|
67
|
+
}] } });
|
|
68
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3Bpbm5lci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy90b2xsZS9zcmMvbGliL3NwaW5uZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLHVCQUF1QixFQUFFLGlCQUFpQixFQUFhLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoSCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLEdBQUcsRUFBcUIsTUFBTSwwQkFBMEIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sWUFBWSxDQUFDOztBQUVoQyxNQUFNLGVBQWUsR0FBRyxHQUFHLENBQUMsMEdBQTBHLEVBQUU7SUFDdEksUUFBUSxFQUFFO1FBQ1IsSUFBSSxFQUFFO1lBQ0osRUFBRSxFQUFFLHdCQUF3QjtZQUM1QixFQUFFLEVBQUUsa0JBQWtCO1lBQ3RCLE9BQU8sRUFBRSxrQkFBa0I7WUFDM0IsRUFBRSxFQUFFLHNCQUFzQjtZQUMxQixFQUFFLEVBQUUsb0JBQW9CO1NBQ3pCO1FBQ0QsT0FBTyxFQUFFO1lBQ1AsT0FBTyxFQUFFLGlCQUFpQjtZQUMxQixPQUFPLEVBQUUsY0FBYztZQUN2QixLQUFLLEVBQUUsdUJBQXVCO1lBQzlCLFdBQVcsRUFBRSxrQkFBa0I7U0FDaEM7S0FDRjtJQUNELGVBQWUsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRTtDQUN6RCxDQUFDLENBQUM7QUFJSDs7OztHQUlHO0FBYUgsTUFBTSxPQUFPLGdCQUFnQjtJQUNWLEdBQUcsR0FBRyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUVqRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUMxQixDQUFDO0lBRUQsa0RBQWtEO0lBQ3pDLElBQUksR0FBeUIsU0FBUyxDQUFDO0lBQ2hELGlGQUFpRjtJQUN4RSxPQUFPLEdBQTRCLFNBQVMsQ0FBQztJQUN0RCxrRkFBa0Y7SUFDekUsS0FBSyxHQUFHLFNBQVMsQ0FBQztJQUMzQiw2RUFBNkU7SUFDcEUsS0FBSyxHQUFHLEVBQUUsQ0FBQztJQUVwQixJQUFJLGFBQWE7UUFDZixPQUFPLEVBQUUsQ0FBQyxlQUFlLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3JGLENBQUM7d0dBbEJVLGdCQUFnQjs0RkFBaEIsZ0JBQWdCLDRLQU5qQjs7OztHQUlULHFHQU5TLFlBQVk7OzRGQVFYLGdCQUFnQjtrQkFaNUIsU0FBUzsrQkFDRSxlQUFlLGNBRWIsSUFBSSxXQUNQLENBQUMsWUFBWSxDQUFDLG1CQUNOLHVCQUF1QixDQUFDLE1BQU0sWUFDckM7Ozs7R0FJVDs4QkFVUSxJQUFJO3NCQUFaLEtBQUs7Z0JBRUcsT0FBTztzQkFBZixLQUFLO2dCQUVHLEtBQUs7c0JBQWIsS0FBSztnQkFFRyxLQUFLO3NCQUFiLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ2hhbmdlRGV0ZWN0b3JSZWYsIE9uQ2hhbmdlcywgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgY3ZhLCB0eXBlIFZhcmlhbnRQcm9wcyB9IGZyb20gJ2NsYXNzLXZhcmlhbmNlLWF1dGhvcml0eSc7XG5pbXBvcnQgeyBjbiB9IGZyb20gJy4vdXRpbHMvY24nO1xuXG5jb25zdCBzcGlubmVyVmFyaWFudHMgPSBjdmEoJ2lubGluZS1ibG9jayBhbmltYXRlLXNwaW4gcm91bmRlZC1mdWxsIGJvcmRlci1zb2xpZCBib3JkZXItY3VycmVudCBib3JkZXItci10cmFuc3BhcmVudCBhbGlnbi1bLTAuMTI1ZW1dJywge1xuICB2YXJpYW50czoge1xuICAgIHNpemU6IHtcbiAgICAgIHhzOiAnaC0zIHctMyBib3JkZXItWzEuNXB4XScsXG4gICAgICBzbTogJ2gtNCB3LTQgYm9yZGVyLTInLFxuICAgICAgZGVmYXVsdDogJ2gtNSB3LTUgYm9yZGVyLTInLFxuICAgICAgbGc6ICdoLTggdy04IGJvcmRlci1bM3B4XScsXG4gICAgICB4bDogJ2gtMTIgdy0xMiBib3JkZXItNCcsXG4gICAgfSxcbiAgICB2YXJpYW50OiB7XG4gICAgICBkZWZhdWx0OiAndGV4dC1mb3JlZ3JvdW5kJyxcbiAgICAgIHByaW1hcnk6ICd0ZXh0LXByaW1hcnknLFxuICAgICAgbXV0ZWQ6ICd0ZXh0LW11dGVkLWZvcmVncm91bmQnLFxuICAgICAgZGVzdHJ1Y3RpdmU6ICd0ZXh0LWRlc3RydWN0aXZlJyxcbiAgICB9LFxuICB9LFxuICBkZWZhdWx0VmFyaWFudHM6IHsgc2l6ZTogJ2RlZmF1bHQnLCB2YXJpYW50OiAnZGVmYXVsdCcgfSxcbn0pO1xuXG5leHBvcnQgdHlwZSBTcGlubmVyUHJvcHMgPSBWYXJpYW50UHJvcHM8dHlwZW9mIHNwaW5uZXJWYXJpYW50cz47XG5cbi8qKlxuICogQW4gaW5kZXRlcm1pbmF0ZSBsb2FkaW5nIGluZGljYXRvci4gUmVuZGVycyBhcyBgcm9sZT1cInN0YXR1c1wiYCB3aXRoIGFcbiAqIHZpc3VhbGx5LWhpZGRlbiBsYWJlbCBzbyBzY3JlZW4gcmVhZGVycyBhbm5vdW5jZSB0aGUgbG9hZGluZyBzdGF0ZS5cbiAqIEBuZXdcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9sbGUtc3Bpbm5lcicsXG4gIHN0eWxlczogWyc6aG9zdCB7IGRpc3BsYXk6IGlubGluZS1mbGV4OyB9J10sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgdGVtcGxhdGU6IGBcbiAgICA8c3BhbiByb2xlPVwic3RhdHVzXCIgW2F0dHIuYXJpYS1sYWJlbF09XCJsYWJlbFwiIFtjbGFzc109XCJjb21wdXRlZENsYXNzXCI+XG4gICAgICA8c3BhbiBjbGFzcz1cInNyLW9ubHlcIj57eyBsYWJlbCB9fTwvc3Bhbj5cbiAgICA8L3NwYW4+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIFNwaW5uZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMge1xuICBwcml2YXRlIHJlYWRvbmx5IGNkciA9IGluamVjdChDaGFuZ2VEZXRlY3RvclJlZik7XG5cbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKiogRGlhbWV0ZXIgb2YgdGhlIHNwaW5uZXIuIEBkZWZhdWx0ICdkZWZhdWx0JyAqL1xuICBASW5wdXQoKSBzaXplOiBTcGlubmVyUHJvcHNbJ3NpemUnXSA9ICdkZWZhdWx0JztcbiAgLyoqIENvbG91ciBvZiB0aGUgc3Bpbm5lciwgaW5oZXJpdGVkIGZyb20gdGhlIHRoZW1lIHRva2Vucy4gQGRlZmF1bHQgJ2RlZmF1bHQnICovXG4gIEBJbnB1dCgpIHZhcmlhbnQ6IFNwaW5uZXJQcm9wc1sndmFyaWFudCddID0gJ2RlZmF1bHQnO1xuICAvKiogQWNjZXNzaWJsZSBsYWJlbCBhbm5vdW5jZWQgd2hpbGUgdGhlIHNwaW5uZXIgaXMgdmlzaWJsZS4gQGRlZmF1bHQgJ0xvYWRpbmcnICovXG4gIEBJbnB1dCgpIGxhYmVsID0gJ0xvYWRpbmcnO1xuICAvKiogRXh0cmEgVGFpbHdpbmQgY2xhc3NlcyBtZXJnZWQgb250byB0aGUgc3Bpbm5lciB2aWEgYGNuKClgIChsYXN0LXdpbnMpLiAqL1xuICBASW5wdXQoKSBjbGFzcyA9ICcnO1xuXG4gIGdldCBjb21wdXRlZENsYXNzKCkge1xuICAgIHJldHVybiBjbihzcGlubmVyVmFyaWFudHMoeyBzaXplOiB0aGlzLnNpemUsIHZhcmlhbnQ6IHRoaXMudmFyaWFudCB9KSwgdGhpcy5jbGFzcyk7XG4gIH1cbn1cbiJdfQ==
|