@tolle_/tolle-ui 18.2.29 → 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 +59 -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 +16453 -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 +26 -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 +8480 -1542
- package/registry/llms-full.txt +2679 -319
- package/registry/llms.txt +43 -4
- package/registry/manifest.json +9090 -1742
- 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,923 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter, forwardRef, ViewChild, ViewChildren, ChangeDetectionStrategy } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
|
+
import { computePosition, flip, shift, offset, autoUpdate } from '@floating-ui/dom';
|
|
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
|
+
const pad2 = (n) => (n < 10 ? '0' + n : String(n));
|
|
10
|
+
/** Seconds elapsed since midnight for a wall-clock time. */
|
|
11
|
+
export function timePartsToSeconds(parts) {
|
|
12
|
+
return parts.hour * 3600 + parts.minute * 60 + parts.second;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parses `HH:mm` or `HH:mm:ss` (24-hour). Returns `null` for anything that
|
|
16
|
+
* is not a well-formed, in-range time — callers treat that as "no value".
|
|
17
|
+
*/
|
|
18
|
+
export function parseTimeString(value) {
|
|
19
|
+
if (typeof value !== 'string')
|
|
20
|
+
return null;
|
|
21
|
+
const match = /^(\d{1,2}):(\d{1,2})(?::(\d{1,2}))?$/.exec(value.trim());
|
|
22
|
+
if (!match)
|
|
23
|
+
return null;
|
|
24
|
+
const hour = Number(match[1]);
|
|
25
|
+
const minute = Number(match[2]);
|
|
26
|
+
const second = match[3] === undefined ? 0 : Number(match[3]);
|
|
27
|
+
if (hour > 23 || minute > 59 || second > 59)
|
|
28
|
+
return null;
|
|
29
|
+
return { hour, minute, second };
|
|
30
|
+
}
|
|
31
|
+
/** Renders a wall-clock time as `HH:mm`, or `HH:mm:ss` when `withSeconds`. */
|
|
32
|
+
export function formatTimeString(parts, withSeconds = false) {
|
|
33
|
+
const base = pad2(parts.hour) + ':' + pad2(parts.minute);
|
|
34
|
+
return withSeconds ? base + ':' + pad2(parts.second) : base;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* 24-hour hour to its 12-hour clock face. Midnight is `12 AM` and noon is
|
|
38
|
+
* `12 PM` — the two values that a naive `hour % 12` gets wrong.
|
|
39
|
+
*/
|
|
40
|
+
export function to12Hour(hour24) {
|
|
41
|
+
const meridiem = hour24 < 12 ? 'AM' : 'PM';
|
|
42
|
+
const hour12 = hour24 % 12 === 0 ? 12 : hour24 % 12;
|
|
43
|
+
return { hour12, meridiem };
|
|
44
|
+
}
|
|
45
|
+
/** 12-hour clock face back to a 24-hour hour. `12 AM` is 0, `12 PM` is 12. */
|
|
46
|
+
export function from12Hour(hour12, meridiem) {
|
|
47
|
+
const base = hour12 % 12; // 12 -> 0, leaves 1..11 alone
|
|
48
|
+
return meridiem === 'PM' ? base + 12 : base;
|
|
49
|
+
}
|
|
50
|
+
const SECONDS_PER_DAY = 24 * 3600;
|
|
51
|
+
const timeOptionVariants = cva('flex w-full shrink-0 cursor-pointer select-none items-center justify-center rounded-md tabular-nums ' +
|
|
52
|
+
'transition-colors focus:outline-none disabled:pointer-events-none disabled:opacity-40', {
|
|
53
|
+
variants: {
|
|
54
|
+
size: {
|
|
55
|
+
xs: 'h-6 px-2 text-[11px]',
|
|
56
|
+
sm: 'h-7 px-2 text-xs',
|
|
57
|
+
default: 'h-8 px-2.5 text-sm',
|
|
58
|
+
lg: 'h-9 px-3 text-base',
|
|
59
|
+
},
|
|
60
|
+
selected: {
|
|
61
|
+
true: 'bg-primary text-primary-foreground hover:bg-primary',
|
|
62
|
+
false: 'text-foreground hover:bg-accent hover:text-accent-foreground',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
defaultVariants: { size: 'default', selected: false },
|
|
66
|
+
});
|
|
67
|
+
/**
|
|
68
|
+
* The bare scrollable hour / minute / second / AM-PM columns, with no trigger
|
|
69
|
+
* and no popover of its own.
|
|
70
|
+
*
|
|
71
|
+
* `tolle-time-picker` wraps this in a floating panel, and
|
|
72
|
+
* `tolle-date-time-picker` sits it beside a calendar — so the option
|
|
73
|
+
* generation, the min/max disabling and the roving keyboard model live here
|
|
74
|
+
* once instead of in both.
|
|
75
|
+
*/
|
|
76
|
+
export class TimeColumnsComponent {
|
|
77
|
+
cdr;
|
|
78
|
+
/** Selected hour in 24-hour form, or `null` when nothing is chosen yet. @default null */
|
|
79
|
+
hour = null;
|
|
80
|
+
/** Selected minute, or `null` when nothing is chosen yet. @default null */
|
|
81
|
+
minute = null;
|
|
82
|
+
/** Selected second, or `null` when nothing is chosen yet. @default null */
|
|
83
|
+
second = null;
|
|
84
|
+
/** Renders a 12-hour clock face with an AM/PM column. @default false */
|
|
85
|
+
use12Hours = false;
|
|
86
|
+
/** Adds the seconds column. @default false */
|
|
87
|
+
showSeconds = false;
|
|
88
|
+
/** Interval between minute entries, in minutes. @default 1 */
|
|
89
|
+
minuteStep = 1;
|
|
90
|
+
/** Interval between second entries, in seconds. @default 1 */
|
|
91
|
+
secondStep = 1;
|
|
92
|
+
/** Earliest selectable time, as seconds since midnight. @default 0 */
|
|
93
|
+
minSeconds = 0;
|
|
94
|
+
/** Latest selectable time, as seconds since midnight. @default 86399 */
|
|
95
|
+
maxSeconds = SECONDS_PER_DAY - 1;
|
|
96
|
+
/** Row height and text size of the entries. @default 'default' */
|
|
97
|
+
size = 'default';
|
|
98
|
+
/** Extra Tailwind classes merged onto the column strip via `cn()` (last-wins). */
|
|
99
|
+
class = '';
|
|
100
|
+
/** Emitted with the full wall-clock time whenever an entry is chosen. */
|
|
101
|
+
timeChange = new EventEmitter();
|
|
102
|
+
listboxes;
|
|
103
|
+
columnsId = 'time-col-' + Math.random().toString(36).slice(2, 11);
|
|
104
|
+
/**
|
|
105
|
+
* Built once per input change rather than read from a getter: a getter would
|
|
106
|
+
* hand `*ngFor` a fresh array on every change-detection pass, so every row —
|
|
107
|
+
* each carrying a click handler — would be torn down and rebuilt on every
|
|
108
|
+
* pass.
|
|
109
|
+
*/
|
|
110
|
+
columns = [];
|
|
111
|
+
/** Roving active entry per column, for `aria-activedescendant`. */
|
|
112
|
+
activeIndex = [];
|
|
113
|
+
cn = cn;
|
|
114
|
+
constructor(cdr) {
|
|
115
|
+
this.cdr = cdr;
|
|
116
|
+
}
|
|
117
|
+
ngOnInit() {
|
|
118
|
+
if (!this.columns.length)
|
|
119
|
+
this.rebuild();
|
|
120
|
+
}
|
|
121
|
+
ngOnChanges() {
|
|
122
|
+
this.rebuild();
|
|
123
|
+
// A bound `class` input is written through Angular's styling path,
|
|
124
|
+
// which does not mark an OnPush view dirty on its own.
|
|
125
|
+
this.cdr.markForCheck();
|
|
126
|
+
}
|
|
127
|
+
get heightClass() {
|
|
128
|
+
switch (this.size) {
|
|
129
|
+
case 'xs':
|
|
130
|
+
return 'max-h-[144px]';
|
|
131
|
+
case 'sm':
|
|
132
|
+
return 'max-h-[168px]';
|
|
133
|
+
case 'lg':
|
|
134
|
+
return 'max-h-[216px]';
|
|
135
|
+
default:
|
|
136
|
+
return 'max-h-[192px]';
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/* ---------------- option generation ---------------- */
|
|
140
|
+
rebuild() {
|
|
141
|
+
const step = (value, fallback) => Number.isFinite(value) && value >= 1 ? Math.floor(value) : fallback;
|
|
142
|
+
const minuteStep = step(this.minuteStep, 1);
|
|
143
|
+
const secondStep = step(this.secondStep, 1);
|
|
144
|
+
const effectiveHour = this.hour ?? 0;
|
|
145
|
+
const effectiveMinute = this.minute ?? 0;
|
|
146
|
+
const meridiem = to12Hour(effectiveHour).meridiem;
|
|
147
|
+
// How far a partially-specified time can stretch. With no seconds column
|
|
148
|
+
// the seconds are pinned to :00, so an hour only reaches :59:00.
|
|
149
|
+
const hourSpan = this.showSeconds ? 3599 : 3540;
|
|
150
|
+
const minuteSpan = this.showSeconds ? 59 : 0;
|
|
151
|
+
const columns = [];
|
|
152
|
+
// Hours
|
|
153
|
+
const hourOptions = [];
|
|
154
|
+
if (this.use12Hours) {
|
|
155
|
+
// Clock-face order: 12, 1, 2 … 11.
|
|
156
|
+
const faces = [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
|
157
|
+
for (const face of faces) {
|
|
158
|
+
const raw = from12Hour(face, meridiem);
|
|
159
|
+
hourOptions.push({
|
|
160
|
+
id: this.columnsId + '-hour-' + face,
|
|
161
|
+
label: pad2(face),
|
|
162
|
+
raw,
|
|
163
|
+
face,
|
|
164
|
+
disabled: this.rangeDisabled(raw * 3600, hourSpan),
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
for (let h = 0; h < 24; h++) {
|
|
170
|
+
hourOptions.push({
|
|
171
|
+
id: this.columnsId + '-hour-' + h,
|
|
172
|
+
label: pad2(h),
|
|
173
|
+
raw: h,
|
|
174
|
+
face: h,
|
|
175
|
+
disabled: this.rangeDisabled(h * 3600, hourSpan),
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
columns.push({ kind: 'hour', label: 'Hour', options: hourOptions });
|
|
180
|
+
// Minutes
|
|
181
|
+
const minuteOptions = [];
|
|
182
|
+
for (let m = 0; m < 60; m += minuteStep) {
|
|
183
|
+
const start = effectiveHour * 3600 + m * 60;
|
|
184
|
+
minuteOptions.push({
|
|
185
|
+
id: this.columnsId + '-minute-' + m,
|
|
186
|
+
label: pad2(m),
|
|
187
|
+
raw: m,
|
|
188
|
+
face: m,
|
|
189
|
+
disabled: this.rangeDisabled(start, minuteSpan),
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
columns.push({ kind: 'minute', label: 'Min', options: minuteOptions });
|
|
193
|
+
// Seconds
|
|
194
|
+
if (this.showSeconds) {
|
|
195
|
+
const secondOptions = [];
|
|
196
|
+
for (let s = 0; s < 60; s += secondStep) {
|
|
197
|
+
const at = effectiveHour * 3600 + effectiveMinute * 60 + s;
|
|
198
|
+
secondOptions.push({
|
|
199
|
+
id: this.columnsId + '-second-' + s,
|
|
200
|
+
label: pad2(s),
|
|
201
|
+
raw: s,
|
|
202
|
+
face: s,
|
|
203
|
+
disabled: this.rangeDisabled(at, 0),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
columns.push({ kind: 'second', label: 'Sec', options: secondOptions });
|
|
207
|
+
}
|
|
208
|
+
// Meridiem
|
|
209
|
+
if (this.use12Hours) {
|
|
210
|
+
const face12 = to12Hour(effectiveHour).hour12;
|
|
211
|
+
const meridiemOptions = ['AM', 'PM'].map((m, i) => {
|
|
212
|
+
const raw = from12Hour(face12, m);
|
|
213
|
+
const halfStart = m === 'AM' ? 0 : 12 * 3600;
|
|
214
|
+
return {
|
|
215
|
+
id: this.columnsId + '-meridiem-' + m,
|
|
216
|
+
label: m,
|
|
217
|
+
raw,
|
|
218
|
+
face: i, // 0 = AM, 1 = PM
|
|
219
|
+
disabled: this.rangeDisabled(halfStart, 12 * 3600 - 1),
|
|
220
|
+
};
|
|
221
|
+
});
|
|
222
|
+
columns.push({ kind: 'meridiem', label: 'AM/PM', options: meridiemOptions });
|
|
223
|
+
}
|
|
224
|
+
this.columns = columns;
|
|
225
|
+
this.syncActiveToSelection();
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* True when nothing in `[start, start + span]` falls inside the allowed
|
|
229
|
+
* window — i.e. picking this entry could not produce a legal time.
|
|
230
|
+
*/
|
|
231
|
+
rangeDisabled(start, span) {
|
|
232
|
+
return start + span < this.minSeconds || start > this.maxSeconds;
|
|
233
|
+
}
|
|
234
|
+
syncActiveToSelection() {
|
|
235
|
+
this.activeIndex = this.columns.map((column) => {
|
|
236
|
+
const idx = column.options.findIndex((o) => this.isSelected(column, o));
|
|
237
|
+
if (idx >= 0)
|
|
238
|
+
return idx;
|
|
239
|
+
const firstEnabled = column.options.findIndex((o) => !o.disabled);
|
|
240
|
+
return firstEnabled >= 0 ? firstEnabled : 0;
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
/* ---------------- selection ---------------- */
|
|
244
|
+
isSelected(column, option) {
|
|
245
|
+
switch (column.kind) {
|
|
246
|
+
case 'hour':
|
|
247
|
+
if (this.hour === null)
|
|
248
|
+
return false;
|
|
249
|
+
return this.use12Hours ? to12Hour(this.hour).hour12 === option.face : this.hour === option.face;
|
|
250
|
+
case 'minute':
|
|
251
|
+
return this.minute !== null && this.minute === option.face;
|
|
252
|
+
case 'second':
|
|
253
|
+
return this.second !== null && this.second === option.face;
|
|
254
|
+
case 'meridiem':
|
|
255
|
+
if (this.hour === null)
|
|
256
|
+
return false;
|
|
257
|
+
return (to12Hour(this.hour).meridiem === 'AM' ? 0 : 1) === option.face;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
isActive(columnIndex, option) {
|
|
261
|
+
const column = this.columns[columnIndex];
|
|
262
|
+
if (!column)
|
|
263
|
+
return false;
|
|
264
|
+
return column.options[this.activeIndex[columnIndex]] === option;
|
|
265
|
+
}
|
|
266
|
+
activeDescendantFor(columnIndex) {
|
|
267
|
+
const column = this.columns[columnIndex];
|
|
268
|
+
return column?.options[this.activeIndex[columnIndex]]?.id ?? null;
|
|
269
|
+
}
|
|
270
|
+
optionClass(column, option, columnIndex) {
|
|
271
|
+
const selected = this.isSelected(column, option);
|
|
272
|
+
return cn(timeOptionVariants({ size: this.size, selected }),
|
|
273
|
+
// The roving highlight has to read as distinct from the committed value,
|
|
274
|
+
// otherwise arrowing around looks like it is already selecting.
|
|
275
|
+
!selected && this.isActive(columnIndex, option) && 'bg-accent text-accent-foreground');
|
|
276
|
+
}
|
|
277
|
+
/** Commits `option` in its column and emits the resulting whole time. */
|
|
278
|
+
choose(column, option, columnIndex) {
|
|
279
|
+
if (option.disabled)
|
|
280
|
+
return;
|
|
281
|
+
const next = {
|
|
282
|
+
hour: this.hour ?? 0,
|
|
283
|
+
minute: this.minute ?? 0,
|
|
284
|
+
second: this.second ?? 0,
|
|
285
|
+
};
|
|
286
|
+
switch (column.kind) {
|
|
287
|
+
case 'hour':
|
|
288
|
+
case 'meridiem':
|
|
289
|
+
next.hour = option.raw;
|
|
290
|
+
break;
|
|
291
|
+
case 'minute':
|
|
292
|
+
next.minute = option.raw;
|
|
293
|
+
break;
|
|
294
|
+
case 'second':
|
|
295
|
+
next.second = option.raw;
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
this.activeIndex[columnIndex] = column.options.indexOf(option);
|
|
299
|
+
this.timeChange.emit(next);
|
|
300
|
+
this.cdr.markForCheck();
|
|
301
|
+
}
|
|
302
|
+
/* ---------------- keyboard ---------------- */
|
|
303
|
+
onColumnKeydown(event, columnIndex) {
|
|
304
|
+
const column = this.columns[columnIndex];
|
|
305
|
+
if (!column)
|
|
306
|
+
return;
|
|
307
|
+
switch (event.key) {
|
|
308
|
+
case 'ArrowDown':
|
|
309
|
+
event.preventDefault();
|
|
310
|
+
this.moveActive(columnIndex, 1);
|
|
311
|
+
break;
|
|
312
|
+
case 'ArrowUp':
|
|
313
|
+
event.preventDefault();
|
|
314
|
+
this.moveActive(columnIndex, -1);
|
|
315
|
+
break;
|
|
316
|
+
case 'Home':
|
|
317
|
+
event.preventDefault();
|
|
318
|
+
this.setActive(columnIndex, 0, 1);
|
|
319
|
+
break;
|
|
320
|
+
case 'End':
|
|
321
|
+
event.preventDefault();
|
|
322
|
+
this.setActive(columnIndex, column.options.length - 1, -1);
|
|
323
|
+
break;
|
|
324
|
+
case 'ArrowLeft':
|
|
325
|
+
event.preventDefault();
|
|
326
|
+
this.focusColumn(columnIndex - 1);
|
|
327
|
+
break;
|
|
328
|
+
case 'ArrowRight':
|
|
329
|
+
event.preventDefault();
|
|
330
|
+
this.focusColumn(columnIndex + 1);
|
|
331
|
+
break;
|
|
332
|
+
case 'Enter':
|
|
333
|
+
case ' ':
|
|
334
|
+
event.preventDefault();
|
|
335
|
+
{
|
|
336
|
+
const option = column.options[this.activeIndex[columnIndex]];
|
|
337
|
+
if (option)
|
|
338
|
+
this.choose(column, option, columnIndex);
|
|
339
|
+
}
|
|
340
|
+
break;
|
|
341
|
+
default:
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
moveActive(columnIndex, delta) {
|
|
346
|
+
const current = this.activeIndex[columnIndex] ?? 0;
|
|
347
|
+
this.setActive(columnIndex, current + delta, delta);
|
|
348
|
+
}
|
|
349
|
+
/** Lands on the first enabled entry at or past `index`, walking `direction`. */
|
|
350
|
+
setActive(columnIndex, index, direction) {
|
|
351
|
+
const column = this.columns[columnIndex];
|
|
352
|
+
if (!column)
|
|
353
|
+
return;
|
|
354
|
+
let i = Math.max(0, Math.min(index, column.options.length - 1));
|
|
355
|
+
while (column.options[i]?.disabled) {
|
|
356
|
+
i += direction;
|
|
357
|
+
if (i < 0 || i >= column.options.length)
|
|
358
|
+
return; // no enabled entry that way
|
|
359
|
+
}
|
|
360
|
+
this.activeIndex[columnIndex] = i;
|
|
361
|
+
this.scrollOptionIntoView(columnIndex, i);
|
|
362
|
+
this.cdr.markForCheck();
|
|
363
|
+
}
|
|
364
|
+
focusColumn(columnIndex) {
|
|
365
|
+
if (columnIndex < 0 || columnIndex >= this.columns.length)
|
|
366
|
+
return;
|
|
367
|
+
this.listboxes?.get(columnIndex)?.nativeElement.focus();
|
|
368
|
+
}
|
|
369
|
+
/** Focuses the first column — used when the panel opens. */
|
|
370
|
+
focusFirstColumn() {
|
|
371
|
+
this.focusColumn(0);
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Centres each column on its selected entry. Scrolls the listbox directly
|
|
375
|
+
* rather than calling `scrollIntoView`, which would also scroll the page
|
|
376
|
+
* behind a fixed-position panel.
|
|
377
|
+
*/
|
|
378
|
+
scrollSelectedIntoView() {
|
|
379
|
+
this.listboxes?.forEach((ref) => {
|
|
380
|
+
const list = ref.nativeElement;
|
|
381
|
+
const selected = list.querySelector('[data-selected="true"]');
|
|
382
|
+
if (!selected)
|
|
383
|
+
return;
|
|
384
|
+
list.scrollTop = selected.offsetTop - list.clientHeight / 2 + selected.clientHeight / 2;
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
scrollOptionIntoView(columnIndex, optionIndex) {
|
|
388
|
+
const list = this.listboxes?.get(columnIndex)?.nativeElement;
|
|
389
|
+
if (!list)
|
|
390
|
+
return;
|
|
391
|
+
const el = list.children[optionIndex];
|
|
392
|
+
if (!el)
|
|
393
|
+
return;
|
|
394
|
+
if (el.offsetTop < list.scrollTop) {
|
|
395
|
+
list.scrollTop = el.offsetTop;
|
|
396
|
+
}
|
|
397
|
+
else if (el.offsetTop + el.clientHeight > list.scrollTop + list.clientHeight) {
|
|
398
|
+
list.scrollTop = el.offsetTop + el.clientHeight - list.clientHeight;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
trackColumn = (_, column) => column.kind;
|
|
402
|
+
trackOption = (_, option) => option.id;
|
|
403
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TimeColumnsComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
404
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: TimeColumnsComponent, isStandalone: true, selector: "tolle-time-columns", inputs: { hour: "hour", minute: "minute", second: "second", use12Hours: "use12Hours", showSeconds: "showSeconds", minuteStep: "minuteStep", secondStep: "secondStep", minSeconds: "minSeconds", maxSeconds: "maxSeconds", size: "size", class: "class" }, outputs: { timeChange: "timeChange" }, viewQueries: [{ propertyName: "listboxes", predicate: ["listbox"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
405
|
+
<div [class]="cn('flex items-stretch gap-1', class)">
|
|
406
|
+
<div
|
|
407
|
+
*ngFor="let column of columns; let ci = index; trackBy: trackColumn"
|
|
408
|
+
class="flex flex-col"
|
|
409
|
+
>
|
|
410
|
+
<div class="px-1 pb-1 text-center text-[10px] font-medium uppercase tracking-wide text-muted-foreground">
|
|
411
|
+
{{ column.label }}
|
|
412
|
+
</div>
|
|
413
|
+
<div
|
|
414
|
+
#listbox
|
|
415
|
+
role="listbox"
|
|
416
|
+
tabindex="0"
|
|
417
|
+
[attr.aria-label]="column.label"
|
|
418
|
+
[attr.aria-activedescendant]="activeDescendantFor(ci)"
|
|
419
|
+
(keydown)="onColumnKeydown($event, ci)"
|
|
420
|
+
[class]="cn(
|
|
421
|
+
'flex flex-col gap-0.5 overflow-y-auto scroll-smooth rounded-md p-1',
|
|
422
|
+
'focus:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
423
|
+
column.kind === 'meridiem' ? 'w-14' : 'w-14',
|
|
424
|
+
heightClass
|
|
425
|
+
)"
|
|
426
|
+
>
|
|
427
|
+
<button
|
|
428
|
+
*ngFor="let option of column.options; trackBy: trackOption"
|
|
429
|
+
type="button"
|
|
430
|
+
role="option"
|
|
431
|
+
tabindex="-1"
|
|
432
|
+
[id]="option.id"
|
|
433
|
+
[attr.aria-selected]="isSelected(column, option)"
|
|
434
|
+
[attr.aria-disabled]="option.disabled"
|
|
435
|
+
[attr.data-selected]="isSelected(column, option)"
|
|
436
|
+
[attr.data-active]="isActive(ci, option)"
|
|
437
|
+
[disabled]="option.disabled"
|
|
438
|
+
[class]="optionClass(column, option, ci)"
|
|
439
|
+
(click)="choose(column, option, ci)"
|
|
440
|
+
>
|
|
441
|
+
{{ option.label }}
|
|
442
|
+
</button>
|
|
443
|
+
</div>
|
|
444
|
+
</div>
|
|
445
|
+
</div>
|
|
446
|
+
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
447
|
+
}
|
|
448
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TimeColumnsComponent, decorators: [{
|
|
449
|
+
type: Component,
|
|
450
|
+
args: [{ selector: 'tolle-time-columns', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
451
|
+
<div [class]="cn('flex items-stretch gap-1', class)">
|
|
452
|
+
<div
|
|
453
|
+
*ngFor="let column of columns; let ci = index; trackBy: trackColumn"
|
|
454
|
+
class="flex flex-col"
|
|
455
|
+
>
|
|
456
|
+
<div class="px-1 pb-1 text-center text-[10px] font-medium uppercase tracking-wide text-muted-foreground">
|
|
457
|
+
{{ column.label }}
|
|
458
|
+
</div>
|
|
459
|
+
<div
|
|
460
|
+
#listbox
|
|
461
|
+
role="listbox"
|
|
462
|
+
tabindex="0"
|
|
463
|
+
[attr.aria-label]="column.label"
|
|
464
|
+
[attr.aria-activedescendant]="activeDescendantFor(ci)"
|
|
465
|
+
(keydown)="onColumnKeydown($event, ci)"
|
|
466
|
+
[class]="cn(
|
|
467
|
+
'flex flex-col gap-0.5 overflow-y-auto scroll-smooth rounded-md p-1',
|
|
468
|
+
'focus:outline-none focus-visible:ring-2 focus-visible:ring-ring',
|
|
469
|
+
column.kind === 'meridiem' ? 'w-14' : 'w-14',
|
|
470
|
+
heightClass
|
|
471
|
+
)"
|
|
472
|
+
>
|
|
473
|
+
<button
|
|
474
|
+
*ngFor="let option of column.options; trackBy: trackOption"
|
|
475
|
+
type="button"
|
|
476
|
+
role="option"
|
|
477
|
+
tabindex="-1"
|
|
478
|
+
[id]="option.id"
|
|
479
|
+
[attr.aria-selected]="isSelected(column, option)"
|
|
480
|
+
[attr.aria-disabled]="option.disabled"
|
|
481
|
+
[attr.data-selected]="isSelected(column, option)"
|
|
482
|
+
[attr.data-active]="isActive(ci, option)"
|
|
483
|
+
[disabled]="option.disabled"
|
|
484
|
+
[class]="optionClass(column, option, ci)"
|
|
485
|
+
(click)="choose(column, option, ci)"
|
|
486
|
+
>
|
|
487
|
+
{{ option.label }}
|
|
488
|
+
</button>
|
|
489
|
+
</div>
|
|
490
|
+
</div>
|
|
491
|
+
</div>
|
|
492
|
+
`, styles: [":host{display:block}\n"] }]
|
|
493
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { hour: [{
|
|
494
|
+
type: Input
|
|
495
|
+
}], minute: [{
|
|
496
|
+
type: Input
|
|
497
|
+
}], second: [{
|
|
498
|
+
type: Input
|
|
499
|
+
}], use12Hours: [{
|
|
500
|
+
type: Input
|
|
501
|
+
}], showSeconds: [{
|
|
502
|
+
type: Input
|
|
503
|
+
}], minuteStep: [{
|
|
504
|
+
type: Input
|
|
505
|
+
}], secondStep: [{
|
|
506
|
+
type: Input
|
|
507
|
+
}], minSeconds: [{
|
|
508
|
+
type: Input
|
|
509
|
+
}], maxSeconds: [{
|
|
510
|
+
type: Input
|
|
511
|
+
}], size: [{
|
|
512
|
+
type: Input
|
|
513
|
+
}], class: [{
|
|
514
|
+
type: Input
|
|
515
|
+
}], timeChange: [{
|
|
516
|
+
type: Output
|
|
517
|
+
}], listboxes: [{
|
|
518
|
+
type: ViewChildren,
|
|
519
|
+
args: ['listbox']
|
|
520
|
+
}] } });
|
|
521
|
+
/* ------------------------------------------------------------------ *
|
|
522
|
+
* The picker
|
|
523
|
+
* ------------------------------------------------------------------ */
|
|
524
|
+
const timePickerTriggerVariants = cva('flex w-full items-center justify-between gap-2 rounded-md border border-input bg-background text-foreground shadow-sm transition-colors ' +
|
|
525
|
+
'focus:outline-none focus-visible:border-primary/80 focus-visible:ring-4 focus-visible:ring-ring/30 ' +
|
|
526
|
+
'disabled:cursor-not-allowed disabled:opacity-50', {
|
|
527
|
+
variants: {
|
|
528
|
+
size: {
|
|
529
|
+
xs: 'h-8 px-2 text-xs',
|
|
530
|
+
sm: 'h-9 px-3 text-sm',
|
|
531
|
+
default: 'h-10 px-3 text-sm',
|
|
532
|
+
lg: 'h-11 px-4 text-base',
|
|
533
|
+
},
|
|
534
|
+
invalid: {
|
|
535
|
+
true: 'border-destructive focus-visible:border-destructive/80 focus-visible:ring-destructive/30',
|
|
536
|
+
false: '',
|
|
537
|
+
},
|
|
538
|
+
},
|
|
539
|
+
defaultVariants: { size: 'default', invalid: false },
|
|
540
|
+
});
|
|
541
|
+
/**
|
|
542
|
+
* A trigger that opens scrollable hour / minute / second columns in a floating
|
|
543
|
+
* panel.
|
|
544
|
+
*
|
|
545
|
+
* The value is a **24-hour `HH:mm` string** (or `HH:mm:ss` when `showSeconds`),
|
|
546
|
+
* regardless of whether the face is rendered as 12-hour — a wall-clock time has
|
|
547
|
+
* no date and no timezone, and a `Date` would invent both. Set
|
|
548
|
+
* `valueType="date"` to exchange `Date` objects instead, in which case the time
|
|
549
|
+
* is written onto today's date (or onto the date already held by the control).
|
|
550
|
+
*
|
|
551
|
+
* Implements `ControlValueAccessor`, so it works with `ngModel` and reactive
|
|
552
|
+
* forms. Use `tolle-date-time-picker` when a date is needed alongside.
|
|
553
|
+
* @new
|
|
554
|
+
*/
|
|
555
|
+
export class TimePickerComponent {
|
|
556
|
+
cdr;
|
|
557
|
+
/**
|
|
558
|
+
* Angular writes a bound `class` input through its styling path, which does
|
|
559
|
+
* not mark an OnPush component dirty — without this hook the component keeps
|
|
560
|
+
* rendering the class it was born with.
|
|
561
|
+
*/
|
|
562
|
+
ngOnChanges() {
|
|
563
|
+
this.cdr.markForCheck();
|
|
564
|
+
}
|
|
565
|
+
/** Text shown on the trigger when no time is selected. @default 'Select a time' */
|
|
566
|
+
placeholder = 'Select a time';
|
|
567
|
+
/** Disables the control. @default false */
|
|
568
|
+
disabled = false;
|
|
569
|
+
/** Renders a 12-hour face with an AM/PM column. The emitted value stays 24-hour. @default false */
|
|
570
|
+
use12Hours = false;
|
|
571
|
+
/** Adds a seconds column and emits `HH:mm:ss`. @default false */
|
|
572
|
+
showSeconds = false;
|
|
573
|
+
/** Interval between minute entries, in minutes. @default 1 */
|
|
574
|
+
minuteStep = 1;
|
|
575
|
+
/** Interval between second entries, in seconds. @default 1 */
|
|
576
|
+
secondStep = 1;
|
|
577
|
+
/** Earliest selectable time as a 24-hour `HH:mm` string; earlier entries are disabled. */
|
|
578
|
+
min;
|
|
579
|
+
/** Latest selectable time as a 24-hour `HH:mm` string; later entries are disabled. */
|
|
580
|
+
max;
|
|
581
|
+
/** Height and text size of the trigger and entries. @default 'default' */
|
|
582
|
+
size = 'default';
|
|
583
|
+
/** Applies the destructive border and focus ring. @default false */
|
|
584
|
+
invalid = false;
|
|
585
|
+
/** Accessible name when there is no associated visible label. @default '' */
|
|
586
|
+
ariaLabel = '';
|
|
587
|
+
/** Exchange `Date` objects instead of `HH:mm` strings through the form control. @default 'string' */
|
|
588
|
+
valueType = 'string';
|
|
589
|
+
/** Extra Tailwind classes merged onto the trigger via `cn()` (last-wins). */
|
|
590
|
+
class = '';
|
|
591
|
+
/** Emitted with the chosen time whenever it changes. */
|
|
592
|
+
valueChange = new EventEmitter();
|
|
593
|
+
/** Emitted when the panel opens. */
|
|
594
|
+
opened = new EventEmitter();
|
|
595
|
+
/** Emitted when the panel closes. */
|
|
596
|
+
closed = new EventEmitter();
|
|
597
|
+
triggerEl;
|
|
598
|
+
panelEl;
|
|
599
|
+
columnsCmp;
|
|
600
|
+
panelId = 'time-picker-panel-' + Math.random().toString(36).slice(2, 11);
|
|
601
|
+
hour = null;
|
|
602
|
+
minute = null;
|
|
603
|
+
second = null;
|
|
604
|
+
isOpen = false;
|
|
605
|
+
cn = cn;
|
|
606
|
+
cleanup;
|
|
607
|
+
/** The date half of a `Date` value, kept so round-tripping does not move the day. */
|
|
608
|
+
dateAnchor = null;
|
|
609
|
+
onChange = () => { };
|
|
610
|
+
onTouched = () => { };
|
|
611
|
+
constructor(cdr) {
|
|
612
|
+
this.cdr = cdr;
|
|
613
|
+
}
|
|
614
|
+
outsideClickHandler = (event) => {
|
|
615
|
+
const target = event.target;
|
|
616
|
+
if (!this.triggerEl?.nativeElement.contains(target) &&
|
|
617
|
+
!this.panelEl?.nativeElement.contains(target)) {
|
|
618
|
+
this.close();
|
|
619
|
+
}
|
|
620
|
+
};
|
|
621
|
+
escapeHandler = (event) => {
|
|
622
|
+
if (event.key === 'Escape' && this.isOpen) {
|
|
623
|
+
event.preventDefault();
|
|
624
|
+
this.close();
|
|
625
|
+
this.triggerEl?.nativeElement.focus();
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
/* ---------------- derived ---------------- */
|
|
629
|
+
/** The current selection as wall-clock parts, or `null` when incomplete. */
|
|
630
|
+
get parts() {
|
|
631
|
+
if (this.hour === null || this.minute === null)
|
|
632
|
+
return null;
|
|
633
|
+
return { hour: this.hour, minute: this.minute, second: this.second ?? 0 };
|
|
634
|
+
}
|
|
635
|
+
get displayValue() {
|
|
636
|
+
const parts = this.parts;
|
|
637
|
+
if (!parts)
|
|
638
|
+
return '';
|
|
639
|
+
if (this.use12Hours) {
|
|
640
|
+
const { hour12, meridiem } = to12Hour(parts.hour);
|
|
641
|
+
const body = String(hour12) +
|
|
642
|
+
':' +
|
|
643
|
+
pad2(parts.minute) +
|
|
644
|
+
(this.showSeconds ? ':' + pad2(parts.second) : '');
|
|
645
|
+
return body + ' ' + meridiem;
|
|
646
|
+
}
|
|
647
|
+
return formatTimeString(parts, this.showSeconds);
|
|
648
|
+
}
|
|
649
|
+
get minSeconds() {
|
|
650
|
+
const parsed = parseTimeString(this.min);
|
|
651
|
+
return parsed ? timePartsToSeconds(parsed) : 0;
|
|
652
|
+
}
|
|
653
|
+
get maxSeconds() {
|
|
654
|
+
const parsed = parseTimeString(this.max);
|
|
655
|
+
return parsed ? timePartsToSeconds(parsed) : SECONDS_PER_DAY - 1;
|
|
656
|
+
}
|
|
657
|
+
get computedTriggerClass() {
|
|
658
|
+
return cn(timePickerTriggerVariants({ size: this.size, invalid: this.invalid }), this.class);
|
|
659
|
+
}
|
|
660
|
+
/* ---------------- open / close ---------------- */
|
|
661
|
+
toggle() {
|
|
662
|
+
this.isOpen ? this.close() : this.open();
|
|
663
|
+
}
|
|
664
|
+
open() {
|
|
665
|
+
if (this.disabled || this.isOpen)
|
|
666
|
+
return;
|
|
667
|
+
this.isOpen = true;
|
|
668
|
+
this.opened.emit();
|
|
669
|
+
this.cdr.markForCheck();
|
|
670
|
+
setTimeout(() => {
|
|
671
|
+
this.updatePosition();
|
|
672
|
+
this.columnsCmp?.scrollSelectedIntoView();
|
|
673
|
+
this.columnsCmp?.focusFirstColumn();
|
|
674
|
+
document.addEventListener('pointerdown', this.outsideClickHandler, true);
|
|
675
|
+
document.addEventListener('keydown', this.escapeHandler, true);
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
close() {
|
|
679
|
+
if (!this.isOpen)
|
|
680
|
+
return;
|
|
681
|
+
this.isOpen = false;
|
|
682
|
+
this.closed.emit();
|
|
683
|
+
this.onTouched();
|
|
684
|
+
this.teardown();
|
|
685
|
+
this.cdr.markForCheck();
|
|
686
|
+
}
|
|
687
|
+
onTriggerKeyDown(event) {
|
|
688
|
+
if (['ArrowDown', 'ArrowUp', 'Enter', ' '].includes(event.key) && !this.isOpen) {
|
|
689
|
+
event.preventDefault();
|
|
690
|
+
this.open();
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
/* ---------------- value ---------------- */
|
|
694
|
+
onTimeChange(parts) {
|
|
695
|
+
this.hour = parts.hour;
|
|
696
|
+
this.minute = parts.minute;
|
|
697
|
+
this.second = parts.second;
|
|
698
|
+
this.emit();
|
|
699
|
+
this.cdr.markForCheck();
|
|
700
|
+
}
|
|
701
|
+
emit() {
|
|
702
|
+
const value = this.currentValue();
|
|
703
|
+
this.onChange(value);
|
|
704
|
+
this.valueChange.emit(value);
|
|
705
|
+
}
|
|
706
|
+
currentValue() {
|
|
707
|
+
const parts = this.parts;
|
|
708
|
+
if (!parts)
|
|
709
|
+
return null;
|
|
710
|
+
if (this.valueType === 'date') {
|
|
711
|
+
const base = this.dateAnchor ?? new Date();
|
|
712
|
+
return new Date(base.getFullYear(), base.getMonth(), base.getDate(), parts.hour, parts.minute, parts.second, 0);
|
|
713
|
+
}
|
|
714
|
+
return formatTimeString(parts, this.showSeconds);
|
|
715
|
+
}
|
|
716
|
+
updatePosition() {
|
|
717
|
+
const trigger = this.triggerEl?.nativeElement;
|
|
718
|
+
const panel = this.panelEl?.nativeElement;
|
|
719
|
+
if (!trigger || !panel)
|
|
720
|
+
return;
|
|
721
|
+
this.cleanup = autoUpdate(trigger, panel, () => {
|
|
722
|
+
computePosition(trigger, panel, {
|
|
723
|
+
strategy: 'fixed',
|
|
724
|
+
placement: 'bottom-start',
|
|
725
|
+
middleware: [offset(4), flip(), shift({ padding: 8 })],
|
|
726
|
+
}).then(({ x, y }) => {
|
|
727
|
+
Object.assign(panel.style, {
|
|
728
|
+
left: x + 'px',
|
|
729
|
+
top: y + 'px',
|
|
730
|
+
visibility: 'visible',
|
|
731
|
+
});
|
|
732
|
+
});
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
teardown() {
|
|
736
|
+
this.cleanup?.();
|
|
737
|
+
this.cleanup = undefined;
|
|
738
|
+
document.removeEventListener('pointerdown', this.outsideClickHandler, true);
|
|
739
|
+
document.removeEventListener('keydown', this.escapeHandler, true);
|
|
740
|
+
}
|
|
741
|
+
ngOnDestroy() {
|
|
742
|
+
this.teardown();
|
|
743
|
+
}
|
|
744
|
+
/* ---------------- ControlValueAccessor ---------------- */
|
|
745
|
+
writeValue(value) {
|
|
746
|
+
let parts = null;
|
|
747
|
+
if (value instanceof Date && !isNaN(value.getTime())) {
|
|
748
|
+
this.dateAnchor = value;
|
|
749
|
+
parts = { hour: value.getHours(), minute: value.getMinutes(), second: value.getSeconds() };
|
|
750
|
+
}
|
|
751
|
+
else if (typeof value === 'string') {
|
|
752
|
+
parts = parseTimeString(value);
|
|
753
|
+
}
|
|
754
|
+
this.hour = parts ? parts.hour : null;
|
|
755
|
+
this.minute = parts ? parts.minute : null;
|
|
756
|
+
this.second = parts ? parts.second : null;
|
|
757
|
+
this.cdr.markForCheck();
|
|
758
|
+
}
|
|
759
|
+
registerOnChange(fn) {
|
|
760
|
+
this.onChange = fn;
|
|
761
|
+
}
|
|
762
|
+
registerOnTouched(fn) {
|
|
763
|
+
this.onTouched = fn;
|
|
764
|
+
}
|
|
765
|
+
setDisabledState(isDisabled) {
|
|
766
|
+
this.disabled = isDisabled;
|
|
767
|
+
if (isDisabled)
|
|
768
|
+
this.close();
|
|
769
|
+
this.cdr.markForCheck();
|
|
770
|
+
}
|
|
771
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TimePickerComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
772
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: TimePickerComponent, isStandalone: true, selector: "tolle-time-picker", inputs: { placeholder: "placeholder", disabled: "disabled", use12Hours: "use12Hours", showSeconds: "showSeconds", minuteStep: "minuteStep", secondStep: "secondStep", min: "min", max: "max", size: "size", invalid: "invalid", ariaLabel: "ariaLabel", valueType: "valueType", class: "class" }, outputs: { valueChange: "valueChange", opened: "opened", closed: "closed" }, providers: [
|
|
773
|
+
{
|
|
774
|
+
provide: NG_VALUE_ACCESSOR,
|
|
775
|
+
useExisting: forwardRef(() => TimePickerComponent),
|
|
776
|
+
multi: true,
|
|
777
|
+
},
|
|
778
|
+
], viewQueries: [{ propertyName: "triggerEl", first: true, predicate: ["trigger"], descendants: true }, { propertyName: "panelEl", first: true, predicate: ["panel"], descendants: true }, { propertyName: "columnsCmp", first: true, predicate: ["columns"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
|
|
779
|
+
<button
|
|
780
|
+
#trigger
|
|
781
|
+
type="button"
|
|
782
|
+
aria-haspopup="dialog"
|
|
783
|
+
[attr.aria-expanded]="isOpen"
|
|
784
|
+
[attr.aria-controls]="isOpen ? panelId : null"
|
|
785
|
+
[attr.aria-label]="ariaLabel || null"
|
|
786
|
+
[attr.data-state]="isOpen ? 'open' : 'closed'"
|
|
787
|
+
[disabled]="disabled"
|
|
788
|
+
[class]="computedTriggerClass"
|
|
789
|
+
(click)="toggle()"
|
|
790
|
+
(keydown)="onTriggerKeyDown($event)"
|
|
791
|
+
>
|
|
792
|
+
<span [class]="cn('truncate', displayValue ? 'text-foreground' : 'text-muted-foreground')">
|
|
793
|
+
{{ displayValue || placeholder }}
|
|
794
|
+
</span>
|
|
795
|
+
<i class="ri-time-line shrink-0 text-muted-foreground" aria-hidden="true"></i>
|
|
796
|
+
</button>
|
|
797
|
+
|
|
798
|
+
<div
|
|
799
|
+
*ngIf="isOpen"
|
|
800
|
+
#panel
|
|
801
|
+
role="dialog"
|
|
802
|
+
[id]="panelId"
|
|
803
|
+
[attr.aria-label]="ariaLabel || 'Choose a time'"
|
|
804
|
+
class="fixed left-0 top-0 z-[9999]"
|
|
805
|
+
style="visibility: hidden"
|
|
806
|
+
>
|
|
807
|
+
<div class="rounded-md border border-border bg-popover p-2 text-popover-foreground shadow-md">
|
|
808
|
+
<tolle-time-columns
|
|
809
|
+
#columns
|
|
810
|
+
[hour]="hour"
|
|
811
|
+
[minute]="minute"
|
|
812
|
+
[second]="second"
|
|
813
|
+
[use12Hours]="use12Hours"
|
|
814
|
+
[showSeconds]="showSeconds"
|
|
815
|
+
[minuteStep]="minuteStep"
|
|
816
|
+
[secondStep]="secondStep"
|
|
817
|
+
[minSeconds]="minSeconds"
|
|
818
|
+
[maxSeconds]="maxSeconds"
|
|
819
|
+
[size]="size"
|
|
820
|
+
(timeChange)="onTimeChange($event)"
|
|
821
|
+
></tolle-time-columns>
|
|
822
|
+
</div>
|
|
823
|
+
</div>
|
|
824
|
+
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: TimeColumnsComponent, selector: "tolle-time-columns", inputs: ["hour", "minute", "second", "use12Hours", "showSeconds", "minuteStep", "secondStep", "minSeconds", "maxSeconds", "size", "class"], outputs: ["timeChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
825
|
+
}
|
|
826
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TimePickerComponent, decorators: [{
|
|
827
|
+
type: Component,
|
|
828
|
+
args: [{ selector: 'tolle-time-picker', standalone: true, imports: [CommonModule, TimeColumnsComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
829
|
+
{
|
|
830
|
+
provide: NG_VALUE_ACCESSOR,
|
|
831
|
+
useExisting: forwardRef(() => TimePickerComponent),
|
|
832
|
+
multi: true,
|
|
833
|
+
},
|
|
834
|
+
], template: `
|
|
835
|
+
<button
|
|
836
|
+
#trigger
|
|
837
|
+
type="button"
|
|
838
|
+
aria-haspopup="dialog"
|
|
839
|
+
[attr.aria-expanded]="isOpen"
|
|
840
|
+
[attr.aria-controls]="isOpen ? panelId : null"
|
|
841
|
+
[attr.aria-label]="ariaLabel || null"
|
|
842
|
+
[attr.data-state]="isOpen ? 'open' : 'closed'"
|
|
843
|
+
[disabled]="disabled"
|
|
844
|
+
[class]="computedTriggerClass"
|
|
845
|
+
(click)="toggle()"
|
|
846
|
+
(keydown)="onTriggerKeyDown($event)"
|
|
847
|
+
>
|
|
848
|
+
<span [class]="cn('truncate', displayValue ? 'text-foreground' : 'text-muted-foreground')">
|
|
849
|
+
{{ displayValue || placeholder }}
|
|
850
|
+
</span>
|
|
851
|
+
<i class="ri-time-line shrink-0 text-muted-foreground" aria-hidden="true"></i>
|
|
852
|
+
</button>
|
|
853
|
+
|
|
854
|
+
<div
|
|
855
|
+
*ngIf="isOpen"
|
|
856
|
+
#panel
|
|
857
|
+
role="dialog"
|
|
858
|
+
[id]="panelId"
|
|
859
|
+
[attr.aria-label]="ariaLabel || 'Choose a time'"
|
|
860
|
+
class="fixed left-0 top-0 z-[9999]"
|
|
861
|
+
style="visibility: hidden"
|
|
862
|
+
>
|
|
863
|
+
<div class="rounded-md border border-border bg-popover p-2 text-popover-foreground shadow-md">
|
|
864
|
+
<tolle-time-columns
|
|
865
|
+
#columns
|
|
866
|
+
[hour]="hour"
|
|
867
|
+
[minute]="minute"
|
|
868
|
+
[second]="second"
|
|
869
|
+
[use12Hours]="use12Hours"
|
|
870
|
+
[showSeconds]="showSeconds"
|
|
871
|
+
[minuteStep]="minuteStep"
|
|
872
|
+
[secondStep]="secondStep"
|
|
873
|
+
[minSeconds]="minSeconds"
|
|
874
|
+
[maxSeconds]="maxSeconds"
|
|
875
|
+
[size]="size"
|
|
876
|
+
(timeChange)="onTimeChange($event)"
|
|
877
|
+
></tolle-time-columns>
|
|
878
|
+
</div>
|
|
879
|
+
</div>
|
|
880
|
+
`, styles: [":host{display:block}\n"] }]
|
|
881
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { placeholder: [{
|
|
882
|
+
type: Input
|
|
883
|
+
}], disabled: [{
|
|
884
|
+
type: Input
|
|
885
|
+
}], use12Hours: [{
|
|
886
|
+
type: Input
|
|
887
|
+
}], showSeconds: [{
|
|
888
|
+
type: Input
|
|
889
|
+
}], minuteStep: [{
|
|
890
|
+
type: Input
|
|
891
|
+
}], secondStep: [{
|
|
892
|
+
type: Input
|
|
893
|
+
}], min: [{
|
|
894
|
+
type: Input
|
|
895
|
+
}], max: [{
|
|
896
|
+
type: Input
|
|
897
|
+
}], size: [{
|
|
898
|
+
type: Input
|
|
899
|
+
}], invalid: [{
|
|
900
|
+
type: Input
|
|
901
|
+
}], ariaLabel: [{
|
|
902
|
+
type: Input
|
|
903
|
+
}], valueType: [{
|
|
904
|
+
type: Input
|
|
905
|
+
}], class: [{
|
|
906
|
+
type: Input
|
|
907
|
+
}], valueChange: [{
|
|
908
|
+
type: Output
|
|
909
|
+
}], opened: [{
|
|
910
|
+
type: Output
|
|
911
|
+
}], closed: [{
|
|
912
|
+
type: Output
|
|
913
|
+
}], triggerEl: [{
|
|
914
|
+
type: ViewChild,
|
|
915
|
+
args: ['trigger']
|
|
916
|
+
}], panelEl: [{
|
|
917
|
+
type: ViewChild,
|
|
918
|
+
args: ['panel']
|
|
919
|
+
}], columnsCmp: [{
|
|
920
|
+
type: ViewChild,
|
|
921
|
+
args: ['columns']
|
|
922
|
+
}] } });
|
|
923
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZS1waWNrZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvdG9sbGUvc3JjL2xpYi90aW1lLXBpY2tlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQWMsU0FBUyxFQUFFLFlBQVksRUFBZ0MsdUJBQXVCLEVBQXdDLE1BQU0sZUFBZSxDQUFDO0FBQ3JOLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQXdCLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDekUsT0FBTyxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNwRixPQUFPLEVBQUUsR0FBRyxFQUFxQixNQUFNLDBCQUEwQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxZQUFZLENBQUM7OztBQWtCaEMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFTLEVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFFbkUsNERBQTREO0FBQzVELE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxLQUFnQjtJQUNqRCxPQUFPLEtBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxHQUFHLEtBQUssQ0FBQyxNQUFNLEdBQUcsRUFBRSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUM7QUFDOUQsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQUMsS0FBZ0M7SUFDOUQsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRO1FB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blpYLG9CQUFvQjs7NEZBNGNwQixtQkFBbUI7a0JBN0QvQixTQUFTOytCQUNFLG1CQUFtQixjQUVqQixJQUFJLFdBQ1AsQ0FBQyxZQUFZLEVBQUUsb0JBQW9CLENBQUMsbUJBQzVCLHVCQUF1QixDQUFDLE1BQU0sYUFDcEM7d0JBQ1Q7NEJBQ0UsT0FBTyxFQUFFLGlCQUFpQjs0QkFDMUIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsb0JBQW9CLENBQUM7NEJBQ2xELEtBQUssRUFBRSxJQUFJO3lCQUNaO3FCQUNGLFlBQ1M7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4Q1Q7c0ZBY1EsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxRQUFRO3NCQUFoQixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRUcsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRUcsR0FBRztzQkFBWCxLQUFLO2dCQUVHLEdBQUc7c0JBQVgsS0FBSztnQkFFRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRUcsT0FBTztzQkFBZixLQUFLO2dCQUVHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBRUcsU0FBUztzQkFBakIsS0FBSztnQkFFRyxLQUFLO3NCQUFiLEtBQUs7Z0JBR0ksV0FBVztzQkFBcEIsTUFBTTtnQkFFRyxNQUFNO3NCQUFmLE1BQU07Z0JBRUcsTUFBTTtzQkFBZixNQUFNO2dCQUVlLFNBQVM7c0JBQTlCLFNBQVM7dUJBQUMsU0FBUztnQkFDQSxPQUFPO3NCQUExQixTQUFTO3VCQUFDLE9BQU87Z0JBQ0ksVUFBVTtzQkFBL0IsU0FBUzt1QkFBQyxTQUFTIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIGZvcndhcmRSZWYsIEVsZW1lbnRSZWYsIFZpZXdDaGlsZCwgVmlld0NoaWxkcmVuLCBRdWVyeUxpc3QsIENoYW5nZURldGVjdG9yUmVmLCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgT25EZXN0cm95LCBPbkluaXQsIE9uQ2hhbmdlcywgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE5HX1ZBTFVFX0FDQ0VTU09SIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgY29tcHV0ZVBvc2l0aW9uLCBmbGlwLCBzaGlmdCwgb2Zmc2V0LCBhdXRvVXBkYXRlIH0gZnJvbSAnQGZsb2F0aW5nLXVpL2RvbSc7XG5pbXBvcnQgeyBjdmEsIHR5cGUgVmFyaWFudFByb3BzIH0gZnJvbSAnY2xhc3MtdmFyaWFuY2UtYXV0aG9yaXR5JztcbmltcG9ydCB7IGNuIH0gZnJvbSAnLi91dGlscy9jbic7XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqXG4gKiBQdXJlIHRpbWUgaGVscGVyc1xuICpcbiAqIFRoZSB3aXJlIGZvcm1hdCBpcyBhIDI0LWhvdXIgYEhIOm1tYCAvIGBISDptbTpzc2Agc3RyaW5nLiBJdCBpc1xuICogdGltZXpvbmUtZnJlZSBhbmQgc3RhYmxlIGFjcm9zcyBzZXJpYWxpc2F0aW9uLCB3aGljaCBhIGBEYXRlYCBpcyBub3Q6XG4gKiBhIGBEYXRlYCBjYXJyaWVzIGEgY2FsZW5kYXIgZGF5IGFuZCBhIFVUQyBvZmZzZXQgdGhhdCBub2JvZHkgY2hvc2Ugd2hlblxuICogYWxsIHRoZSB1c2VyIGRpZCB3YXMgcGljayBcIjI6MzAgUE1cIi5cbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4vKiogQSB3YWxsLWNsb2NrIHRpbWUgd2l0aCBubyBkYXRlIGFuZCBubyB0aW1lem9uZSBhdHRhY2hlZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGltZVBhcnRzIHtcbiAgaG91cjogbnVtYmVyO1xuICBtaW51dGU6IG51bWJlcjtcbiAgc2Vjb25kOiBudW1iZXI7XG59XG5cbmNvbnN0IHBhZDIgPSAobjogbnVtYmVyKTogc3RyaW5nID0+IChuIDwgMTAgPyAnMCcgKyBuIDogU3RyaW5nKG4pKTtcblxuLyoqIFNlY29uZHMgZWxhcHNlZCBzaW5jZSBtaWRuaWdodCBmb3IgYSB3YWxsLWNsb2NrIHRpbWUuICovXG5leHBvcnQgZnVuY3Rpb24gdGltZVBhcnRzVG9TZWNvbmRzKHBhcnRzOiBUaW1lUGFydHMpOiBudW1iZXIge1xuICByZXR1cm4gcGFydHMuaG91ciAqIDM2MDAgKyBwYXJ0cy5taW51dGUgKiA2MCArIHBhcnRzLnNlY29uZDtcbn1cblxuLyoqXG4gKiBQYXJzZXMgYEhIOm1tYCBvciBgSEg6bW06c3NgICgyNC1ob3VyKS4gUmV0dXJucyBgbnVsbGAgZm9yIGFueXRoaW5nIHRoYXRcbiAqIGlzIG5vdCBhIHdlbGwtZm9ybWVkLCBpbi1yYW5nZSB0aW1lIOKAlCBjYWxsZXJzIHRyZWF0IHRoYXQgYXMgXCJubyB2YWx1ZVwiLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VUaW1lU3RyaW5nKHZhbHVlOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogVGltZVBhcnRzIHwgbnVsbCB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSByZXR1cm4gbnVsbDtcbiAgY29uc3QgbWF0Y2ggPSAvXihcXGR7MSwyfSk6KFxcZHsxLDJ9KSg/OjooXFxkezEsMn0pKT8kLy5leGVjKHZhbHVlLnRyaW0oKSk7XG4gIGlmICghbWF0Y2gpIHJldHVybiBudWxsO1xuXG4gIGNvbnN0IGhvdXIgPSBOdW1iZXIobWF0Y2hbMV0pO1xuICBjb25zdCBtaW51dGUgPSBOdW1iZXIobWF0Y2hbMl0pO1xuICBjb25zdCBzZWNvbmQgPSBtYXRjaFszXSA9PT0gdW5kZWZpbmVkID8gMCA6IE51bWJlcihtYXRjaFszXSk7XG5cbiAgaWYgKGhvdXIgPiAyMyB8fCBtaW51dGUgPiA1OSB8fCBzZWNvbmQgPiA1OSkgcmV0dXJuIG51bGw7XG4gIHJldHVybiB7IGhvdXIsIG1pbnV0ZSwgc2Vjb25kIH07XG59XG5cbi8qKiBSZW5kZXJzIGEgd2FsbC1jbG9jayB0aW1lIGFzIGBISDptbWAsIG9yIGBISDptbTpzc2Agd2hlbiBgd2l0aFNlY29uZHNgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFRpbWVTdHJpbmcocGFydHM6IFRpbWVQYXJ0cywgd2l0aFNlY29uZHMgPSBmYWxzZSk6IHN0cmluZyB7XG4gIGNvbnN0IGJhc2UgPSBwYWQyKHBhcnRzLmhvdXIpICsgJzonICsgcGFkMihwYXJ0cy5taW51dGUpO1xuICByZXR1cm4gd2l0aFNlY29uZHMgPyBiYXNlICsgJzonICsgcGFkMihwYXJ0cy5zZWNvbmQpIDogYmFzZTtcbn1cblxuLyoqXG4gKiAyNC1ob3VyIGhvdXIgdG8gaXRzIDEyLWhvdXIgY2xvY2sgZmFjZS4gTWlkbmlnaHQgaXMgYDEyIEFNYCBhbmQgbm9vbiBpc1xuICogYDEyIFBNYCDigJQgdGhlIHR3byB2YWx1ZXMgdGhhdCBhIG5haXZlIGBob3VyICUgMTJgIGdldHMgd3JvbmcuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0bzEySG91cihob3VyMjQ6IG51bWJlcik6IHsgaG91cjEyOiBudW1iZXI7IG1lcmlkaWVtOiAnQU0nIHwgJ1BNJyB9IHtcbiAgY29uc3QgbWVyaWRpZW06ICdBTScgfCAnUE0nID0gaG91cjI0IDwgMTIgPyAnQU0nIDogJ1BNJztcbiAgY29uc3QgaG91cjEyID0gaG91cjI0ICUgMTIgPT09IDAgPyAxMiA6IGhvdXIyNCAlIDEyO1xuICByZXR1cm4geyBob3VyMTIsIG1lcmlkaWVtIH07XG59XG5cbi8qKiAxMi1ob3VyIGNsb2NrIGZhY2UgYmFjayB0byBhIDI0LWhvdXIgaG91ci4gYDEyIEFNYCBpcyAwLCBgMTIgUE1gIGlzIDEyLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZyb20xMkhvdXIoaG91cjEyOiBudW1iZXIsIG1lcmlkaWVtOiAnQU0nIHwgJ1BNJyk6IG51bWJlciB7XG4gIGNvbnN0IGJhc2UgPSBob3VyMTIgJSAxMjsgLy8gMTIgLT4gMCwgbGVhdmVzIDEuLjExIGFsb25lXG4gIHJldHVybiBtZXJpZGllbSA9PT0gJ1BNJyA/IGJhc2UgKyAxMiA6IGJhc2U7XG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqXG4gKiBDb2x1bW4gbW9kZWxcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4vKiogV2hpY2ggdW5pdCBhIGNvbHVtbiBvZiB0aGUgcGlja2VyIHNjcm9sbHMgdGhyb3VnaC4gKi9cbmV4cG9ydCB0eXBlIFRpbWVDb2x1bW5LaW5kID0gJ2hvdXInIHwgJ21pbnV0ZScgfCAnc2Vjb25kJyB8ICdtZXJpZGllbSc7XG5cbi8qKiBPbmUgZW50cnkgaW5zaWRlIGEgdGltZSBjb2x1bW4uICovXG5leHBvcnQgaW50ZXJmYWNlIFRpbWVPcHRpb24ge1xuICAvKiogU3RhYmxlIGlkZW50aXR5IGZvciBgdHJhY2tCeWAgYW5kIGBhcmlhLWFjdGl2ZWRlc2NlbmRhbnRgLiAqL1xuICBpZDogc3RyaW5nO1xuICAvKiogVGV4dCBzaG93biB0byB0aGUgdXNlci4gKi9cbiAgbGFiZWw6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSAyNC1ob3VyIHZhbHVlIHRoaXMgZW50cnkgY29tbWl0cyBmb3IgaXRzIGNvbHVtbi4gRm9yIGEgYG1lcmlkaWVtYFxuICAgKiBjb2x1bW4gdGhpcyBpcyB0aGUgcmVzdWx0aW5nIDI0LWhvdXIgKmhvdXIqLlxuICAgKi9cbiAgcmF3OiBudW1iZXI7XG4gIC8qKiBWYWx1ZSB1c2VkIGZvciB0aGUgc2VsZWN0ZWQgY29tcGFyaXNvbiAoY2xvY2stZmFjZSB2YWx1ZSBmb3IgaG91cnMpLiAqL1xuICBmYWNlOiBudW1iZXI7XG4gIGRpc2FibGVkOiBib29sZWFuO1xufVxuXG4vKiogQSBzY3JvbGxhYmxlIGNvbHVtbiBvZiB0aGUgcGlja2VyLiAqL1xuZXhwb3J0IGludGVyZmFjZSBUaW1lQ29sdW1uIHtcbiAga2luZDogVGltZUNvbHVtbktpbmQ7XG4gIGxhYmVsOiBzdHJpbmc7XG4gIG9wdGlvbnM6IFRpbWVPcHRpb25bXTtcbn1cblxuY29uc3QgU0VDT05EU19QRVJfREFZID0gMjQgKiAzNjAwO1xuXG5jb25zdCB0aW1lT3B0aW9uVmFyaWFudHMgPSBjdmEoXG4gICdmbGV4IHctZnVsbCBzaHJpbmstMCBjdXJzb3ItcG9pbnRlciBzZWxlY3Qtbm9uZSBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcm91bmRlZC1tZCB0YWJ1bGFyLW51bXMgJyArXG4gICAgJ3RyYW5zaXRpb24tY29sb3JzIGZvY3VzOm91dGxpbmUtbm9uZSBkaXNhYmxlZDpwb2ludGVyLWV2ZW50cy1ub25lIGRpc2FibGVkOm9wYWNpdHktNDAnLFxuICB7XG4gICAgdmFyaWFudHM6IHtcbiAgICAgIHNpemU6IHtcbiAgICAgICAgeHM6ICdoLTYgcHgtMiB0ZXh0LVsxMXB4XScsXG4gICAgICAgIHNtOiAnaC03IHB4LTIgdGV4dC14cycsXG4gICAgICAgIGRlZmF1bHQ6ICdoLTggcHgtMi41IHRleHQtc20nLFxuICAgICAgICBsZzogJ2gtOSBweC0zIHRleHQtYmFzZScsXG4gICAgICB9LFxuICAgICAgc2VsZWN0ZWQ6IHtcbiAgICAgICAgdHJ1ZTogJ2JnLXByaW1hcnkgdGV4dC1wcmltYXJ5LWZvcmVncm91bmQgaG92ZXI6YmctcHJpbWFyeScsXG4gICAgICAgIGZhbHNlOiAndGV4dC1mb3JlZ3JvdW5kIGhvdmVyOmJnLWFjY2VudCBob3Zlcjp0ZXh0LWFjY2VudC1mb3JlZ3JvdW5kJyxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBkZWZhdWx0VmFyaWFudHM6IHsgc2l6ZTogJ2RlZmF1bHQnLCBzZWxlY3RlZDogZmFsc2UgfSxcbiAgfVxuKTtcblxuLyoqIFZhcmlhbnQgcHJvcHMgZm9yIHRoZSBvcHRpb24gcm93cyBpbnNpZGUgYSB0aW1lIGNvbHVtbi4gKi9cbmV4cG9ydCB0eXBlIFRpbWVDb2x1bW5zUHJvcHMgPSBWYXJpYW50UHJvcHM8dHlwZW9mIHRpbWVPcHRpb25WYXJpYW50cz47XG5cbi8qKlxuICogVGhlIGJhcmUgc2Nyb2xsYWJsZSBob3VyIC8gbWludXRlIC8gc2Vjb25kIC8gQU0tUE0gY29sdW1ucywgd2l0aCBubyB0cmlnZ2VyXG4gKiBhbmQgbm8gcG9wb3ZlciBvZiBpdHMgb3duLlxuICpcbiAqIGB0b2xsZS10aW1lLXBpY2tlcmAgd3JhcHMgdGhpcyBpbiBhIGZsb2F0aW5nIHBhbmVsLCBhbmRcbiAqIGB0b2xsZS1kYXRlLXRpbWUtcGlja2VyYCBzaXRzIGl0IGJlc2lkZSBhIGNhbGVuZGFyIOKAlCBzbyB0aGUgb3B0aW9uXG4gKiBnZW5lcmF0aW9uLCB0aGUgbWluL21heCBkaXNhYmxpbmcgYW5kIHRoZSByb3Zpbmcga2V5Ym9hcmQgbW9kZWwgbGl2ZSBoZXJlXG4gKiBvbmNlIGluc3RlYWQgb2YgaW4gYm90aC5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9sbGUtdGltZS1jb2x1bW5zJyxcbiAgc3R5bGVzOiBbJzpob3N0IHsgZGlzcGxheTogYmxvY2s7IH0nXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgW2NsYXNzXT1cImNuKCdmbGV4IGl0ZW1zLXN0cmV0Y2ggZ2FwLTEnLCBjbGFzcylcIj5cbiAgICAgIDxkaXZcbiAgICAgICAgKm5nRm9yPVwibGV0IGNvbHVtbiBvZiBjb2x1bW5zOyBsZXQgY2kgPSBpbmRleDsgdHJhY2tCeTogdHJhY2tDb2x1bW5cIlxuICAgICAgICBjbGFzcz1cImZsZXggZmxleC1jb2xcIlxuICAgICAgPlxuICAgICAgICA8ZGl2IGNsYXNzPVwicHgtMSBwYi0xIHRleHQtY2VudGVyIHRleHQtWzEwcHhdIGZvbnQtbWVkaXVtIHVwcGVyY2FzZSB0cmFja2luZy13aWRlIHRleHQtbXV0ZWQtZm9yZWdyb3VuZFwiPlxuICAgICAgICAgIHt7IGNvbHVtbi5sYWJlbCB9fVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdlxuICAgICAgICAgICNsaXN0Ym94XG4gICAgICAgICAgcm9sZT1cImxpc3Rib3hcIlxuICAgICAgICAgIHRhYmluZGV4PVwiMFwiXG4gICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJjb2x1bW4ubGFiZWxcIlxuICAgICAgICAgIFthdHRyLmFyaWEtYWN0aXZlZGVzY2VuZGFudF09XCJhY3RpdmVEZXNjZW5kYW50Rm9yKGNpKVwiXG4gICAgICAgICAgKGtleWRvd24pPVwib25Db2x1bW5LZXlkb3duKCRldmVudCwgY2kpXCJcbiAgICAgICAgICBbY2xhc3NdPVwiY24oXG4gICAgICAgICAgICAnZmxleCBmbGV4LWNvbCBnYXAtMC41IG92ZXJmbG93LXktYXV0byBzY3JvbGwtc21vb3RoIHJvdW5kZWQtbWQgcC0xJyxcbiAgICAgICAgICAgICdmb2N1czpvdXRsaW5lLW5vbmUgZm9jdXMtdmlzaWJsZTpyaW5nLTIgZm9jdXMtdmlzaWJsZTpyaW5nLXJpbmcnLFxuICAgICAgICAgICAgY29sdW1uLmtpbmQgPT09ICdtZXJpZGllbScgPyAndy0xNCcgOiAndy0xNCcsXG4gICAgICAgICAgICBoZWlnaHRDbGFzc1xuICAgICAgICAgIClcIlxuICAgICAgICA+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgKm5nRm9yPVwibGV0IG9wdGlvbiBvZiBjb2x1bW4ub3B0aW9uczsgdHJhY2tCeTogdHJhY2tPcHRpb25cIlxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICByb2xlPVwib3B0aW9uXCJcbiAgICAgICAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgICAgICAgW2lkXT1cIm9wdGlvbi5pZFwiXG4gICAgICAgICAgICBbYXR0ci5hcmlhLXNlbGVjdGVkXT1cImlzU2VsZWN0ZWQoY29sdW1uLCBvcHRpb24pXCJcbiAgICAgICAgICAgIFthdHRyLmFyaWEtZGlzYWJsZWRdPVwib3B0aW9uLmRpc2FibGVkXCJcbiAgICAgICAgICAgIFthdHRyLmRhdGEtc2VsZWN0ZWRdPVwiaXNTZWxlY3RlZChjb2x1bW4sIG9wdGlvbilcIlxuICAgICAgICAgICAgW2F0dHIuZGF0YS1hY3RpdmVdPVwiaXNBY3RpdmUoY2ksIG9wdGlvbilcIlxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cIm9wdGlvbi5kaXNhYmxlZFwiXG4gICAgICAgICAgICBbY2xhc3NdPVwib3B0aW9uQ2xhc3MoY29sdW1uLCBvcHRpb24sIGNpKVwiXG4gICAgICAgICAgICAoY2xpY2spPVwiY2hvb3NlKGNvbHVtbiwgb3B0aW9uLCBjaSlcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIHt7IG9wdGlvbi5sYWJlbCB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBUaW1lQ29sdW1uc0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcbiAgLyoqIFNlbGVjdGVkIGhvdXIgaW4gMjQtaG91ciBmb3JtLCBvciBgbnVsbGAgd2hlbiBub3RoaW5nIGlzIGNob3NlbiB5ZXQuIEBkZWZhdWx0IG51bGwgKi9cbiAgQElucHV0KCkgaG91cjogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gIC8qKiBTZWxlY3RlZCBtaW51dGUsIG9yIGBudWxsYCB3aGVuIG5vdGhpbmcgaXMgY2hvc2VuIHlldC4gQGRlZmF1bHQgbnVsbCAqL1xuICBASW5wdXQoKSBtaW51dGU6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICAvKiogU2VsZWN0ZWQgc2Vjb25kLCBvciBgbnVsbGAgd2hlbiBub3RoaW5nIGlzIGNob3NlbiB5ZXQuIEBkZWZhdWx0IG51bGwgKi9cbiAgQElucHV0KCkgc2Vjb25kOiBudW1iZXIgfCBudWxsID0gbnVsbDtcbiAgLyoqIFJlbmRlcnMgYSAxMi1ob3VyIGNsb2NrIGZhY2Ugd2l0aCBhbiBBTS9QTSBjb2x1bW4uIEBkZWZhdWx0IGZhbHNlICovXG4gIEBJbnB1dCgpIHVzZTEySG91cnMgPSBmYWxzZTtcbiAgLyoqIEFkZHMgdGhlIHNlY29uZHMgY29sdW1uLiBAZGVmYXVsdCBmYWxzZSAqL1xuICBASW5wdXQoKSBzaG93U2Vjb25kcyA9IGZhbHNlO1xuICAvKiogSW50ZXJ2YWwgYmV0d2VlbiBtaW51dGUgZW50cmllcywgaW4gbWludXRlcy4gQGRlZmF1bHQgMSAqL1xuICBASW5wdXQoKSBtaW51dGVTdGVwID0gMTtcbiAgLyoqIEludGVydmFsIGJldHdlZW4gc2Vjb25kIGVudHJpZXMsIGluIHNlY29uZHMuIEBkZWZhdWx0IDEgKi9cbiAgQElucHV0KCkgc2Vjb25kU3RlcCA9IDE7XG4gIC8qKiBFYXJsaWVzdCBzZWxlY3RhYmxlIHRpbWUsIGFzIHNlY29uZHMgc2luY2UgbWlkbmlnaHQuIEBkZWZhdWx0IDAgKi9cbiAgQElucHV0KCkgbWluU2Vjb25kcyA9IDA7XG4gIC8qKiBMYXRlc3Qgc2VsZWN0YWJsZSB0aW1lLCBhcyBzZWNvbmRzIHNpbmNlIG1pZG5pZ2h0LiBAZGVmYXVsdCA4NjM5OSAqL1xuICBASW5wdXQoKSBtYXhTZWNvbmRzID0gU0VDT05EU19QRVJfREFZIC0gMTtcbiAgLyoqIFJvdyBoZWlnaHQgYW5kIHRleHQgc2l6ZSBvZiB0aGUgZW50cmllcy4gQGRlZmF1bHQgJ2RlZmF1bHQnICovXG4gIEBJbnB1dCgpIHNpemU6IFRpbWVDb2x1bW5zUHJvcHNbJ3NpemUnXSA9ICdkZWZhdWx0JztcbiAgLyoqIEV4dHJhIFRhaWx3aW5kIGNsYXNzZXMgbWVyZ2VkIG9udG8gdGhlIGNvbHVtbiBzdHJpcCB2aWEgYGNuKClgIChsYXN0LXdpbnMpLiAqL1xuICBASW5wdXQoKSBjbGFzcyA9ICcnO1xuXG4gIC8qKiBFbWl0dGVkIHdpdGggdGhlIGZ1bGwgd2FsbC1jbG9jayB0aW1lIHdoZW5ldmVyIGFuIGVudHJ5IGlzIGNob3Nlbi4gKi9cbiAgQE91dHB1dCgpIHRpbWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPFRpbWVQYXJ0cz4oKTtcblxuICBAVmlld0NoaWxkcmVuKCdsaXN0Ym94JykgbGlzdGJveGVzPzogUXVlcnlMaXN0PEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+PjtcblxuICByZWFkb25seSBjb2x1bW5zSWQgPSAndGltZS1jb2wtJyArIE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnNsaWNlKDIsIDExKTtcblxuICAvKipcbiAgICogQnVpbHQgb25jZSBwZXIgaW5wdXQgY2hhbmdlIHJhdGhlciB0aGFuIHJlYWQgZnJvbSBhIGdldHRlcjogYSBnZXR0ZXIgd291bGRcbiAgICogaGFuZCBgKm5nRm9yYCBhIGZyZXNoIGFycmF5IG9uIGV2ZXJ5IGNoYW5nZS1kZXRlY3Rpb24gcGFzcywgc28gZXZlcnkgcm93IOKAlFxuICAgKiBlYWNoIGNhcnJ5aW5nIGEgY2xpY2sgaGFuZGxlciDigJQgd291bGQgYmUgdG9ybiBkb3duIGFuZCByZWJ1aWx0IG9uIGV2ZXJ5XG4gICAqIHBhc3MuXG4gICAqL1xuICBjb2x1bW5zOiBUaW1lQ29sdW1uW10gPSBbXTtcbiAgLyoqIFJvdmluZyBhY3RpdmUgZW50cnkgcGVyIGNvbHVtbiwgZm9yIGBhcmlhLWFjdGl2ZWRlc2NlbmRhbnRgLiAqL1xuICBhY3RpdmVJbmRleDogbnVtYmVyW10gPSBbXTtcblxuICBwcm90ZWN0ZWQgY24gPSBjbjtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWYpIHt9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbHVtbnMubGVuZ3RoKSB0aGlzLnJlYnVpbGQoKTtcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKCk6IHZvaWQge1xuICAgIHRoaXMucmVidWlsZCgpO1xuICBcbiAgICAvLyBBIGJvdW5kIGBjbGFzc2AgaW5wdXQgaXMgd3JpdHRlbiB0aHJvdWdoIEFuZ3VsYXIncyBzdHlsaW5nIHBhdGgsXG4gICAgLy8gd2hpY2ggZG9lcyBub3QgbWFyayBhbiBPblB1c2ggdmlldyBkaXJ0eSBvbiBpdHMgb3duLlxuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgZ2V0IGhlaWdodENsYXNzKCk6IHN0cmluZyB7XG4gICAgc3dpdGNoICh0aGlzLnNpemUpIHtcbiAgICAgIGNhc2UgJ3hzJzpcbiAgICAgICAgcmV0dXJuICdtYXgtaC1bMTQ0cHhdJztcbiAgICAgIGNhc2UgJ3NtJzpcbiAgICAgICAgcmV0dXJuICdtYXgtaC1bMTY4cHhdJztcbiAgICAgIGNhc2UgJ2xnJzpcbiAgICAgICAgcmV0dXJuICdtYXgtaC1bMjE2cHhdJztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiAnbWF4LWgtWzE5MnB4XSc7XG4gICAgfVxuICB9XG5cbiAgLyogLS0tLS0tLS0tLS0tLS0tLSBvcHRpb24gZ2VuZXJhdGlvbiAtLS0tLS0tLS0tLS0tLS0tICovXG5cbiAgcHJpdmF0ZSByZWJ1aWxkKCk6IHZvaWQge1xuICAgIGNvbnN0IHN0ZXAgPSAodmFsdWU6IG51bWJlciwgZmFsbGJhY2s6IG51bWJlcikgPT5cbiAgICAgIE51bWJlci5pc0Zpbml0ZSh2YWx1ZSkgJiYgdmFsdWUgPj0gMSA/IE1hdGguZmxvb3IodmFsdWUpIDogZmFsbGJhY2s7XG5cbiAgICBjb25zdCBtaW51dGVTdGVwID0gc3RlcCh0aGlzLm1pbnV0ZVN0ZXAsIDEpO1xuICAgIGNvbnN0IHNlY29uZFN0ZXAgPSBzdGVwKHRoaXMuc2Vjb25kU3RlcCwgMSk7XG4gICAgY29uc3QgZWZmZWN0aXZlSG91ciA9IHRoaXMuaG91ciA/PyAwO1xuICAgIGNvbnN0IGVmZmVjdGl2ZU1pbnV0ZSA9IHRoaXMubWludXRlID8/IDA7XG4gICAgY29uc3QgbWVyaWRpZW0gPSB0bzEySG91cihlZmZlY3RpdmVIb3VyKS5tZXJpZGllbTtcblxuICAgIC8vIEhvdyBmYXIgYSBwYXJ0aWFsbHktc3BlY2lmaWVkIHRpbWUgY2FuIHN0cmV0Y2guIFdpdGggbm8gc2Vjb25kcyBjb2x1bW5cbiAgICAvLyB0aGUgc2Vjb25kcyBhcmUgcGlubmVkIHRvIDowMCwgc28gYW4gaG91ciBvbmx5IHJlYWNoZXMgOjU5OjAwLlxuICAgIGNvbnN0IGhvdXJTcGFuID0gdGhpcy5zaG93U2Vjb25kcyA/IDM1OTkgOiAzNTQwO1xuICAgIGNvbnN0IG1pbnV0ZVNwYW4gPSB0aGlzLnNob3dTZWNvbmRzID8gNTkgOiAwO1xuXG4gICAgY29uc3QgY29sdW1uczogVGltZUNvbHVtbltdID0gW107XG5cbiAgICAvLyBIb3Vyc1xuICAgIGNvbnN0IGhvdXJPcHRpb25zOiBUaW1lT3B0aW9uW10gPSBbXTtcbiAgICBpZiAodGhpcy51c2UxMkhvdXJzKSB7XG4gICAgICAvLyBDbG9jay1mYWNlIG9yZGVyOiAxMiwgMSwgMiDigKYgMTEuXG4gICAgICBjb25zdCBmYWNlcyA9IFsxMiwgMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOSwgMTAsIDExXTtcbiAgICAgIGZvciAoY29uc3QgZmFjZSBvZiBmYWNlcykge1xuICAgICAgICBjb25zdCByYXcgPSBmcm9tMTJIb3VyKGZhY2UsIG1lcmlkaWVtKTtcbiAgICAgICAgaG91ck9wdGlvbnMucHVzaCh7XG4gICAgICAgICAgaWQ6IHRoaXMuY29sdW1uc0lkICsgJy1ob3VyLScgKyBmYWNlLFxuICAgICAgICAgIGxhYmVsOiBwYWQyKGZhY2UpLFxuICAgICAgICAgIHJhdyxcbiAgICAgICAgICBmYWNlLFxuICAgICAgICAgIGRpc2FibGVkOiB0aGlzLnJhbmdlRGlzYWJsZWQocmF3ICogMzYwMCwgaG91clNwYW4pLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChsZXQgaCA9IDA7IGggPCAyNDsgaCsrKSB7XG4gICAgICAgIGhvdXJPcHRpb25zLnB1c2goe1xuICAgICAgICAgIGlkOiB0aGlzLmNvbHVtbnNJZCArICctaG91ci0nICsgaCxcbiAgICAgICAgICBsYWJlbDogcGFkMihoKSxcbiAgICAgICAgICByYXc6IGgsXG4gICAgICAgICAgZmFjZTogaCxcbiAgICAgICAgICBkaXNhYmxlZDogdGhpcy5yYW5nZURpc2FibGVkKGggKiAzNjAwLCBob3VyU3BhbiksXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgICBjb2x1bW5zLnB1c2goeyBraW5kOiAnaG91cicsIGxhYmVsOiAnSG91cicsIG9wdGlvbnM6IGhvdXJPcHRpb25zIH0pO1xuXG4gICAgLy8gTWludXRlc1xuICAgIGNvbnN0IG1pbnV0ZU9wdGlvbnM6IFRpbWVPcHRpb25bXSA9IFtdO1xuICAgIGZvciAobGV0IG0gPSAwOyBtIDwgNjA7IG0gKz0gbWludXRlU3RlcCkge1xuICAgICAgY29uc3Qgc3RhcnQgPSBlZmZlY3RpdmVIb3VyICogMzYwMCArIG0gKiA2MDtcbiAgICAgIG1pbnV0ZU9wdGlvbnMucHVzaCh7XG4gICAgICAgIGlkOiB0aGlzLmNvbHVtbnNJZCArICctbWludXRlLScgKyBtLFxuICAgICAgICBsYWJlbDogcGFkMihtKSxcbiAgICAgICAgcmF3OiBtLFxuICAgICAgICBmYWNlOiBtLFxuICAgICAgICBkaXNhYmxlZDogdGhpcy5yYW5nZURpc2FibGVkKHN0YXJ0LCBtaW51dGVTcGFuKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICBjb2x1bW5zLnB1c2goeyBraW5kOiAnbWludXRlJywgbGFiZWw6ICdNaW4nLCBvcHRpb25zOiBtaW51dGVPcHRpb25zIH0pO1xuXG4gICAgLy8gU2Vjb25kc1xuICAgIGlmICh0aGlzLnNob3dTZWNvbmRzKSB7XG4gICAgICBjb25zdCBzZWNvbmRPcHRpb25zOiBUaW1lT3B0aW9uW10gPSBbXTtcbiAgICAgIGZvciAobGV0IHMgPSAwOyBzIDwgNjA7IHMgKz0gc2Vjb25kU3RlcCkge1xuICAgICAgICBjb25zdCBhdCA9IGVmZmVjdGl2ZUhvdXIgKiAzNjAwICsgZWZmZWN0aXZlTWludXRlICogNjAgKyBzO1xuICAgICAgICBzZWNvbmRPcHRpb25zLnB1c2goe1xuICAgICAgICAgIGlkOiB0aGlzLmNvbHVtbnNJZCArICctc2Vjb25kLScgKyBzLFxuICAgICAgICAgIGxhYmVsOiBwYWQyKHMpLFxuICAgICAgICAgIHJhdzogcyxcbiAgICAgICAgICBmYWNlOiBzLFxuICAgICAgICAgIGRpc2FibGVkOiB0aGlzLnJhbmdlRGlzYWJsZWQoYXQsIDApLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIGNvbHVtbnMucHVzaCh7IGtpbmQ6ICdzZWNvbmQnLCBsYWJlbDogJ1NlYycsIG9wdGlvbnM6IHNlY29uZE9wdGlvbnMgfSk7XG4gICAgfVxuXG4gICAgLy8gTWVyaWRpZW1cbiAgICBpZiAodGhpcy51c2UxMkhvdXJzKSB7XG4gICAgICBjb25zdCBmYWNlMTIgPSB0bzEySG91cihlZmZlY3RpdmVIb3VyKS5ob3VyMTI7XG4gICAgICBjb25zdCBtZXJpZGllbU9wdGlvbnM6IFRpbWVPcHRpb25bXSA9IChbJ0FNJywgJ1BNJ10gYXMgY29uc3QpLm1hcCgobSwgaSkgPT4ge1xuICAgICAgICBjb25zdCByYXcgPSBmcm9tMTJIb3VyKGZhY2UxMiwgbSk7XG4gICAgICAgIGNvbnN0IGhhbGZTdGFydCA9IG0gPT09ICdBTScgPyAwIDogMTIgKiAzNjAwO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGlkOiB0aGlzLmNvbHVtbnNJZCArICctbWVyaWRpZW0tJyArIG0sXG4gICAgICAgICAgbGFiZWw6IG0sXG4gICAgICAgICAgcmF3LFxuICAgICAgICAgIGZhY2U6IGksIC8vIDAgPSBBTSwgMSA9IFBNXG4gICAgICAgICAgZGlzYWJsZWQ6IHRoaXMucmFuZ2VEaXNhYmxlZChoYWxmU3RhcnQsIDEyICogMzYwMCAtIDEpLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgICBjb2x1bW5zLnB1c2goeyBraW5kOiAnbWVyaWRpZW0nLCBsYWJlbDogJ0FNL1BNJywgb3B0aW9uczogbWVyaWRpZW1PcHRpb25zIH0pO1xuICAgIH1cblxuICAgIHRoaXMuY29sdW1ucyA9IGNvbHVtbnM7XG4gICAgdGhpcy5zeW5jQWN0aXZlVG9TZWxlY3Rpb24oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcnVlIHdoZW4gbm90aGluZyBpbiBgW3N0YXJ0LCBzdGFydCArIHNwYW5dYCBmYWxscyBpbnNpZGUgdGhlIGFsbG93ZWRcbiAgICogd2luZG93IOKAlCBpLmUuIHBpY2tpbmcgdGhpcyBlbnRyeSBjb3VsZCBub3QgcHJvZHVjZSBhIGxlZ2FsIHRpbWUuXG4gICAqL1xuICBwcml2YXRlIHJhbmdlRGlzYWJsZWQoc3RhcnQ6IG51bWJlciwgc3BhbjogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHN0YXJ0ICsgc3BhbiA8IHRoaXMubWluU2Vjb25kcyB8fCBzdGFydCA+IHRoaXMubWF4U2Vjb25kcztcbiAgfVxuXG4gIHByaXZhdGUgc3luY0FjdGl2ZVRvU2VsZWN0aW9uKCk6IHZvaWQge1xuICAgIHRoaXMuYWN0aXZlSW5kZXggPSB0aGlzLmNvbHVtbnMubWFwKChjb2x1bW4pID0+IHtcbiAgICAgIGNvbnN0IGlkeCA9IGNvbHVtbi5vcHRpb25zLmZpbmRJbmRleCgobykgPT4gdGhpcy5pc1NlbGVjdGVkKGNvbHVtbiwgbykpO1xuICAgICAgaWYgKGlkeCA+PSAwKSByZXR1cm4gaWR4O1xuICAgICAgY29uc3QgZmlyc3RFbmFibGVkID0gY29sdW1uLm9wdGlvbnMuZmluZEluZGV4KChvKSA9PiAhby5kaXNhYmxlZCk7XG4gICAgICByZXR1cm4gZmlyc3RFbmFibGVkID49IDAgPyBmaXJzdEVuYWJsZWQgOiAwO1xuICAgIH0pO1xuICB9XG5cbiAgLyogLS0tLS0tLS0tLS0tLS0tLSBzZWxlY3Rpb24gLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4gIGlzU2VsZWN0ZWQoY29sdW1uOiBUaW1lQ29sdW1uLCBvcHRpb246IFRpbWVPcHRpb24pOiBib29sZWFuIHtcbiAgICBzd2l0Y2ggKGNvbHVtbi5raW5kKSB7XG4gICAgICBjYXNlICdob3VyJzpcbiAgICAgICAgaWYgKHRoaXMuaG91ciA9PT0gbnVsbCkgcmV0dXJuIGZhbHNlO1xuICAgICAgICByZXR1cm4gdGhpcy51c2UxMkhvdXJzID8gdG8xMkhvdXIodGhpcy5ob3VyKS5ob3VyMTIgPT09IG9wdGlvbi5mYWNlIDogdGhpcy5ob3VyID09PSBvcHRpb24uZmFjZTtcbiAgICAgIGNhc2UgJ21pbnV0ZSc6XG4gICAgICAgIHJldHVybiB0aGlzLm1pbnV0ZSAhPT0gbnVsbCAmJiB0aGlzLm1pbnV0ZSA9PT0gb3B0aW9uLmZhY2U7XG4gICAgICBjYXNlICdzZWNvbmQnOlxuICAgICAgICByZXR1cm4gdGhpcy5zZWNvbmQgIT09IG51bGwgJiYgdGhpcy5zZWNvbmQgPT09IG9wdGlvbi5mYWNlO1xuICAgICAgY2FzZSAnbWVyaWRpZW0nOlxuICAgICAgICBpZiAodGhpcy5ob3VyID09PSBudWxsKSByZXR1cm4gZmFsc2U7XG4gICAgICAgIHJldHVybiAodG8xMkhvdXIodGhpcy5ob3VyKS5tZXJpZGllbSA9PT0gJ0FNJyA/IDAgOiAxKSA9PT0gb3B0aW9uLmZhY2U7XG4gICAgfVxuICB9XG5cbiAgaXNBY3RpdmUoY29sdW1uSW5kZXg6IG51bWJlciwgb3B0aW9uOiBUaW1lT3B0aW9uKTogYm9vbGVhbiB7XG4gICAgY29uc3QgY29sdW1uID0gdGhpcy5jb2x1bW5zW2NvbHVtbkluZGV4XTtcbiAgICBpZiAoIWNvbHVtbikgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiBjb2x1bW4ub3B0aW9uc1t0aGlzLmFjdGl2ZUluZGV4W2NvbHVtbkluZGV4XV0gPT09IG9wdGlvbjtcbiAgfVxuXG4gIGFjdGl2ZURlc2NlbmRhbnRGb3IoY29sdW1uSW5kZXg6IG51bWJlcik6IHN0cmluZyB8IG51bGwge1xuICAgIGNvbnN0IGNvbHVtbiA9IHRoaXMuY29sdW1uc1tjb2x1bW5JbmRleF07XG4gICAgcmV0dXJuIGNvbHVtbj8ub3B0aW9uc1t0aGlzLmFjdGl2ZUluZGV4W2NvbHVtbkluZGV4XV0/LmlkID8/IG51bGw7XG4gIH1cblxuICBvcHRpb25DbGFzcyhjb2x1bW46IFRpbWVDb2x1bW4sIG9wdGlvbjogVGltZU9wdGlvbiwgY29sdW1uSW5kZXg6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3Qgc2VsZWN0ZWQgPSB0aGlzLmlzU2VsZWN0ZWQoY29sdW1uLCBvcHRpb24pO1xuICAgIHJldHVybiBjbihcbiAgICAgIHRpbWVPcHRpb25WYXJpYW50cyh7IHNpemU6IHRoaXMuc2l6ZSwgc2VsZWN0ZWQgfSksXG4gICAgICAvLyBUaGUgcm92aW5nIGhpZ2hsaWdodCBoYXMgdG8gcmVhZCBhcyBkaXN0aW5jdCBmcm9tIHRoZSBjb21taXR0ZWQgdmFsdWUsXG4gICAgICAvLyBvdGhlcndpc2UgYXJyb3dpbmcgYXJvdW5kIGxvb2tzIGxpa2UgaXQgaXMgYWxyZWFkeSBzZWxlY3RpbmcuXG4gICAgICAhc2VsZWN0ZWQgJiYgdGhpcy5pc0FjdGl2ZShjb2x1bW5JbmRleCwgb3B0aW9uKSAmJiAnYmctYWNjZW50IHRleHQtYWNjZW50LWZvcmVncm91bmQnXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBDb21taXRzIGBvcHRpb25gIGluIGl0cyBjb2x1bW4gYW5kIGVtaXRzIHRoZSByZXN1bHRpbmcgd2hvbGUgdGltZS4gKi9cbiAgY2hvb3NlKGNvbHVtbjogVGltZUNvbHVtbiwgb3B0aW9uOiBUaW1lT3B0aW9uLCBjb2x1bW5JbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKG9wdGlvbi5kaXNhYmxlZCkgcmV0dXJuO1xuXG4gICAgY29uc3QgbmV4dDogVGltZVBhcnRzID0ge1xuICAgICAgaG91cjogdGhpcy5ob3VyID8/IDAsXG4gICAgICBtaW51dGU6IHRoaXMubWludXRlID8/IDAsXG4gICAgICBzZWNvbmQ6IHRoaXMuc2Vjb25kID8/IDAsXG4gICAgfTtcblxuICAgIHN3aXRjaCAoY29sdW1uLmtpbmQpIHtcbiAgICAgIGNhc2UgJ2hvdXInOlxuICAgICAgY2FzZSAnbWVyaWRpZW0nOlxuICAgICAgICBuZXh0LmhvdXIgPSBvcHRpb24ucmF3O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ21pbnV0ZSc6XG4gICAgICAgIG5leHQubWludXRlID0gb3B0aW9uLnJhdztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdzZWNvbmQnOlxuICAgICAgICBuZXh0LnNlY29uZCA9IG9wdGlvbi5yYXc7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHRoaXMuYWN0aXZlSW5kZXhbY29sdW1uSW5kZXhdID0gY29sdW1uLm9wdGlvbnMuaW5kZXhPZihvcHRpb24pO1xuICAgIHRoaXMudGltZUNoYW5nZS5lbWl0KG5leHQpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgLyogLS0tLS0tLS0tLS0tLS0tLSBrZXlib2FyZCAtLS0tLS0tLS0tLS0tLS0tICovXG5cbiAgb25Db2x1bW5LZXlkb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50LCBjb2x1bW5JbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgY29sdW1uID0gdGhpcy5jb2x1bW5zW2NvbHVtbkluZGV4XTtcbiAgICBpZiAoIWNvbHVtbikgcmV0dXJuO1xuXG4gICAgc3dpdGNoIChldmVudC5rZXkpIHtcbiAgICAgIGNhc2UgJ0Fycm93RG93bic6XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMubW92ZUFjdGl2ZShjb2x1bW5JbmRleCwgMSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnQXJyb3dVcCc6XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMubW92ZUFjdGl2ZShjb2x1bW5JbmRleCwgLTEpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ0hvbWUnOlxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLnNldEFjdGl2ZShjb2x1bW5JbmRleCwgMCwgMSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnRW5kJzpcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgdGhpcy5zZXRBY3RpdmUoY29sdW1uSW5kZXgsIGNvbHVtbi5vcHRpb25zLmxlbmd0aCAtIDEsIC0xKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdBcnJvd0xlZnQnOlxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB0aGlzLmZvY3VzQ29sdW1uKGNvbHVtbkluZGV4IC0gMSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnQXJyb3dSaWdodCc6XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHRoaXMuZm9jdXNDb2x1bW4oY29sdW1uSW5kZXggKyAxKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdFbnRlcic6XG4gICAgICBjYXNlICcgJzpcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAge1xuICAgICAgICAgIGNvbnN0IG9wdGlvbiA9IGNvbHVtbi5vcHRpb25zW3RoaXMuYWN0aXZlSW5kZXhbY29sdW1uSW5kZXhdXTtcbiAgICAgICAgICBpZiAob3B0aW9uKSB0aGlzLmNob29zZShjb2x1bW4sIG9wdGlvbiwgY29sdW1uSW5kZXgpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbW92ZUFjdGl2ZShjb2x1bW5JbmRleDogbnVtYmVyLCBkZWx0YTogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgY3VycmVudCA9IHRoaXMuYWN0aXZlSW5kZXhbY29sdW1uSW5kZXhdID8/IDA7XG4gICAgdGhpcy5zZXRBY3RpdmUoY29sdW1uSW5kZXgsIGN1cnJlbnQgKyBkZWx0YSwgZGVsdGEpO1xuICB9XG5cbiAgLyoqIExhbmRzIG9uIHRoZSBmaXJzdCBlbmFibGVkIGVudHJ5IGF0IG9yIHBhc3QgYGluZGV4YCwgd2Fsa2luZyBgZGlyZWN0aW9uYC4gKi9cbiAgcHJpdmF0ZSBzZXRBY3RpdmUoY29sdW1uSW5kZXg6IG51bWJlciwgaW5kZXg6IG51bWJlciwgZGlyZWN0aW9uOiBudW1iZXIpOiB2b2lkIHtcbiAgICBjb25zdCBjb2x1bW4gPSB0aGlzLmNvbHVtbnNbY29sdW1uSW5kZXhdO1xuICAgIGlmICghY29sdW1uKSByZXR1cm47XG5cbiAgICBsZXQgaSA9IE1hdGgubWF4KDAsIE1hdGgubWluKGluZGV4LCBjb2x1bW4ub3B0aW9ucy5sZW5ndGggLSAxKSk7XG4gICAgd2hpbGUgKGNvbHVtbi5vcHRpb25zW2ldPy5kaXNhYmxlZCkge1xuICAgICAgaSArPSBkaXJlY3Rpb247XG4gICAgICBpZiAoaSA8IDAgfHwgaSA+PSBjb2x1bW4ub3B0aW9ucy5sZW5ndGgpIHJldHVybjsgLy8gbm8gZW5hYmxlZCBlbnRyeSB0aGF0IHdheVxuICAgIH1cblxuICAgIHRoaXMuYWN0aXZlSW5kZXhbY29sdW1uSW5kZXhdID0gaTtcbiAgICB0aGlzLnNjcm9sbE9wdGlvbkludG9WaWV3KGNvbHVtbkluZGV4LCBpKTtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIHByaXZhdGUgZm9jdXNDb2x1bW4oY29sdW1uSW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGlmIChjb2x1bW5JbmRleCA8IDAgfHwgY29sdW1uSW5kZXggPj0gdGhpcy5jb2x1bW5zLmxlbmd0aCkgcmV0dXJuO1xuICAgIHRoaXMubGlzdGJveGVzPy5nZXQoY29sdW1uSW5kZXgpPy5uYXRpdmVFbGVtZW50LmZvY3VzKCk7XG4gIH1cblxuICAvKiogRm9jdXNlcyB0aGUgZmlyc3QgY29sdW1uIOKAlCB1c2VkIHdoZW4gdGhlIHBhbmVsIG9wZW5zLiAqL1xuICBmb2N1c0ZpcnN0Q29sdW1uKCk6IHZvaWQge1xuICAgIHRoaXMuZm9jdXNDb2x1bW4oMCk7XG4gIH1cblxuICAvKipcbiAgICogQ2VudHJlcyBlYWNoIGNvbHVtbiBvbiBpdHMgc2VsZWN0ZWQgZW50cnkuIFNjcm9sbHMgdGhlIGxpc3Rib3ggZGlyZWN0bHlcbiAgICogcmF0aGVyIHRoYW4gY2FsbGluZyBgc2Nyb2xsSW50b1ZpZXdgLCB3aGljaCB3b3VsZCBhbHNvIHNjcm9sbCB0aGUgcGFnZVxuICAgKiBiZWhpbmQgYSBmaXhlZC1wb3NpdGlvbiBwYW5lbC5cbiAgICovXG4gIHNjcm9sbFNlbGVjdGVkSW50b1ZpZXcoKTogdm9pZCB7XG4gICAgdGhpcy5saXN0Ym94ZXM/LmZvckVhY2goKHJlZikgPT4ge1xuICAgICAgY29uc3QgbGlzdCA9IHJlZi5uYXRpdmVFbGVtZW50O1xuICAgICAgY29uc3Qgc2VsZWN0ZWQgPSBsaXN0LnF1ZXJ5U2VsZWN0b3IoJ1tkYXRhLXNlbGVjdGVkPVwidHJ1ZVwiXScpIGFzIEhUTUxFbGVtZW50IHwgbnVsbDtcbiAgICAgIGlmICghc2VsZWN0ZWQpIHJldHVybjtcbiAgICAgIGxpc3Quc2Nyb2xsVG9wID0gc2VsZWN0ZWQub2Zmc2V0VG9wIC0gbGlzdC5jbGllbnRIZWlnaHQgLyAyICsgc2VsZWN0ZWQuY2xpZW50SGVpZ2h0IC8gMjtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc2Nyb2xsT3B0aW9uSW50b1ZpZXcoY29sdW1uSW5kZXg6IG51bWJlciwgb3B0aW9uSW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnN0IGxpc3QgPSB0aGlzLmxpc3Rib3hlcz8uZ2V0KGNvbHVtbkluZGV4KT8ubmF0aXZlRWxlbWVudDtcbiAgICBpZiAoIWxpc3QpIHJldHVybjtcbiAgICBjb25zdCBlbCA9IGxpc3QuY2hpbGRyZW5bb3B0aW9uSW5kZXhdIGFzIEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgIGlmICghZWwpIHJldHVybjtcblxuICAgIGlmIChlbC5vZmZzZXRUb3AgPCBsaXN0LnNjcm9sbFRvcCkge1xuICAgICAgbGlzdC5zY3JvbGxUb3AgPSBlbC5vZmZzZXRUb3A7XG4gICAgfSBlbHNlIGlmIChlbC5vZmZzZXRUb3AgKyBlbC5jbGllbnRIZWlnaHQgPiBsaXN0LnNjcm9sbFRvcCArIGxpc3QuY2xpZW50SGVpZ2h0KSB7XG4gICAgICBsaXN0LnNjcm9sbFRvcCA9IGVsLm9mZnNldFRvcCArIGVsLmNsaWVudEhlaWdodCAtIGxpc3QuY2xpZW50SGVpZ2h0O1xuICAgIH1cbiAgfVxuXG4gIHRyYWNrQ29sdW1uID0gKF86IG51bWJlciwgY29sdW1uOiBUaW1lQ29sdW1uKSA9PiBjb2x1bW4ua2luZDtcbiAgdHJhY2tPcHRpb24gPSAoXzogbnVtYmVyLCBvcHRpb246IFRpbWVPcHRpb24pID0+IG9wdGlvbi5pZDtcbn1cblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tICpcbiAqIFRoZSBwaWNrZXJcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5jb25zdCB0aW1lUGlja2VyVHJpZ2dlclZhcmlhbnRzID0gY3ZhKFxuICAnZmxleCB3LWZ1bGwgaXRlbXMtY2VudGVyIGp1c3RpZnktYmV0d2VlbiBnYXAtMiByb3VuZGVkLW1kIGJvcmRlciBib3JkZXItaW5wdXQgYmctYmFja2dyb3VuZCB0ZXh0LWZvcmVncm91bmQgc2hhZG93LXNtIHRyYW5zaXRpb24tY29sb3JzICcgK1xuICAgICdmb2N1czpvdXRsaW5lLW5vbmUgZm9jdXMtdmlzaWJsZTpib3JkZXItcHJpbWFyeS84MCBmb2N1cy12aXNpYmxlOnJpbmctNCBmb2N1cy12aXNpYmxlOnJpbmctcmluZy8zMCAnICtcbiAgICAnZGlzYWJsZWQ6Y3Vyc29yLW5vdC1hbGxvd2VkIGRpc2FibGVkOm9wYWNpdHktNTAnLFxuICB7XG4gICAgdmFyaWFudHM6IHtcbiAgICAgIHNpemU6IHtcbiAgICAgICAgeHM6ICdoLTggcHgtMiB0ZXh0LXhzJyxcbiAgICAgICAgc206ICdoLTkgcHgtMyB0ZXh0LXNtJyxcbiAgICAgICAgZGVmYXVsdDogJ2gtMTAgcHgtMyB0ZXh0LXNtJyxcbiAgICAgICAgbGc6ICdoLTExIHB4LTQgdGV4dC1iYXNlJyxcbiAgICAgIH0sXG4gICAgICBpbnZhbGlkOiB7XG4gICAgICAgIHRydWU6ICdib3JkZXItZGVzdHJ1Y3RpdmUgZm9jdXMtdmlzaWJsZTpib3JkZXItZGVzdHJ1Y3RpdmUvODAgZm9jdXMtdmlzaWJsZTpyaW5nLWRlc3RydWN0aXZlLzMwJyxcbiAgICAgICAgZmFsc2U6ICcnLFxuICAgICAgfSxcbiAgICB9LFxuICAgIGRlZmF1bHRWYXJpYW50czogeyBzaXplOiAnZGVmYXVsdCcsIGludmFsaWQ6IGZhbHNlIH0sXG4gIH1cbik7XG5cbi8qKiBWYXJpYW50IHByb3BzIGZvciB0aGUgdGltZSBwaWNrZXIgdHJpZ2dlci4gKi9cbmV4cG9ydCB0eXBlIFRpbWVQaWNrZXJQcm9wcyA9IFZhcmlhbnRQcm9wczx0eXBlb2YgdGltZVBpY2tlclRyaWdnZXJWYXJpYW50cz47XG5cbi8qKlxuICogQSB0cmlnZ2VyIHRoYXQgb3BlbnMgc2Nyb2xsYWJsZSBob3VyIC8gbWludXRlIC8gc2Vjb25kIGNvbHVtbnMgaW4gYSBmbG9hdGluZ1xuICogcGFuZWwuXG4gKlxuICogVGhlIHZhbHVlIGlzIGEgKioyNC1ob3VyIGBISDptbWAgc3RyaW5nKiogKG9yIGBISDptbTpzc2Agd2hlbiBgc2hvd1NlY29uZHNgKSxcbiAqIHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB0aGUgZmFjZSBpcyByZW5kZXJlZCBhcyAxMi1ob3VyIOKAlCBhIHdhbGwtY2xvY2sgdGltZSBoYXNcbiAqIG5vIGRhdGUgYW5kIG5vIHRpbWV6b25lLCBhbmQgYSBgRGF0ZWAgd291bGQgaW52ZW50IGJvdGguIFNldFxuICogYHZhbHVlVHlwZT1cImRhdGVcImAgdG8gZXhjaGFuZ2UgYERhdGVgIG9iamVjdHMgaW5zdGVhZCwgaW4gd2hpY2ggY2FzZSB0aGUgdGltZVxuICogaXMgd3JpdHRlbiBvbnRvIHRvZGF5J3MgZGF0ZSAob3Igb250byB0aGUgZGF0ZSBhbHJlYWR5IGhlbGQgYnkgdGhlIGNvbnRyb2wpLlxuICpcbiAqIEltcGxlbWVudHMgYENvbnRyb2xWYWx1ZUFjY2Vzc29yYCwgc28gaXQgd29ya3Mgd2l0aCBgbmdNb2RlbGAgYW5kIHJlYWN0aXZlXG4gKiBmb3Jtcy4gVXNlIGB0b2xsZS1kYXRlLXRpbWUtcGlja2VyYCB3aGVuIGEgZGF0ZSBpcyBuZWVkZWQgYWxvbmdzaWRlLlxuICogQG5ld1xuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0b2xsZS10aW1lLXBpY2tlcicsXG4gIHN0eWxlczogWyc6aG9zdCB7IGRpc3BsYXk6IGJsb2NrOyB9J10sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIFRpbWVDb2x1bW5zQ29tcG9uZW50XSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHByb3ZpZGVyczogW1xuICAgIHtcbiAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gVGltZVBpY2tlckNvbXBvbmVudCksXG4gICAgICBtdWx0aTogdHJ1ZSxcbiAgICB9LFxuICBdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxidXR0b25cbiAgICAgICN0cmlnZ2VyXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgIGFyaWEtaGFzcG9wdXA9XCJkaWFsb2dcIlxuICAgICAgW2F0dHIuYXJpYS1leHBhbmRlZF09XCJpc09wZW5cIlxuICAgICAgW2F0dHIuYXJpYS1jb250cm9sc109XCJpc09wZW4gPyBwYW5lbElkIDogbnVsbFwiXG4gICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbCB8fCBudWxsXCJcbiAgICAgIFthdHRyLmRhdGEtc3RhdGVdPVwiaXNPcGVuID8gJ29wZW4nIDogJ2Nsb3NlZCdcIlxuICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgIFtjbGFzc109XCJjb21wdXRlZFRyaWdnZXJDbGFzc1wiXG4gICAgICAoY2xpY2spPVwidG9nZ2xlKClcIlxuICAgICAgKGtleWRvd24pPVwib25UcmlnZ2VyS2V5RG93bigkZXZlbnQpXCJcbiAgICA+XG4gICAgICA8c3BhbiBbY2xhc3NdPVwiY24oJ3RydW5jYXRlJywgZGlzcGxheVZhbHVlID8gJ3RleHQtZm9yZWdyb3VuZCcgOiAndGV4dC1tdXRlZC1mb3JlZ3JvdW5kJylcIj5cbiAgICAgICAge3sgZGlzcGxheVZhbHVlIHx8IHBsYWNlaG9sZGVyIH19XG4gICAgICA8L3NwYW4+XG4gICAgICA8aSBjbGFzcz1cInJpLXRpbWUtbGluZSBzaHJpbmstMCB0ZXh0LW11dGVkLWZvcmVncm91bmRcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgPC9idXR0b24+XG5cbiAgICA8ZGl2XG4gICAgICAqbmdJZj1cImlzT3BlblwiXG4gICAgICAjcGFuZWxcbiAgICAgIHJvbGU9XCJkaWFsb2dcIlxuICAgICAgW2lkXT1cInBhbmVsSWRcIlxuICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWwgfHwgJ0Nob29zZSBhIHRpbWUnXCJcbiAgICAgIGNsYXNzPVwiZml4ZWQgbGVmdC0wIHRvcC0wIHotWzk5OTldXCJcbiAgICAgIHN0eWxlPVwidmlzaWJpbGl0eTogaGlkZGVuXCJcbiAgICA+XG4gICAgICA8ZGl2IGNsYXNzPVwicm91bmRlZC1tZCBib3JkZXIgYm9yZGVyLWJvcmRlciBiZy1wb3BvdmVyIHAtMiB0ZXh0LXBvcG92ZXItZm9yZWdyb3VuZCBzaGFkb3ctbWRcIj5cbiAgICAgICAgPHRvbGxlLXRpbWUtY29sdW1uc1xuICAgICAgICAgICNjb2x1bW5zXG4gICAgICAgICAgW2hvdXJdPVwiaG91clwiXG4gICAgICAgICAgW21pbnV0ZV09XCJtaW51dGVcIlxuICAgICAgICAgIFtzZWNvbmRdPVwic2Vjb25kXCJcbiAgICAgICAgICBbdXNlMTJIb3Vyc109XCJ1c2UxMkhvdXJzXCJcbiAgICAgICAgICBbc2hvd1NlY29uZHNdPVwic2hvd1NlY29uZHNcIlxuICAgICAgICAgIFttaW51dGVTdGVwXT1cIm1pbnV0ZVN0ZXBcIlxuICAgICAgICAgIFtzZWNvbmRTdGVwXT1cInNlY29uZFN0ZXBcIlxuICAgICAgICAgIFttaW5TZWNvbmRzXT1cIm1pblNlY29uZHNcIlxuICAgICAgICAgIFttYXhTZWNvbmRzXT1cIm1heFNlY29uZHNcIlxuICAgICAgICAgIFtzaXplXT1cInNpemVcIlxuICAgICAgICAgICh0aW1lQ2hhbmdlKT1cIm9uVGltZUNoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgPjwvdG9sbGUtdGltZS1jb2x1bW5zPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIFRpbWVQaWNrZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkNoYW5nZXMsIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBPbkRlc3Ryb3kge1xuXG4gIC8qKlxuICAgKiBBbmd1bGFyIHdyaXRlcyBhIGJvdW5kIGBjbGFzc2AgaW5wdXQgdGhyb3VnaCBpdHMgc3R5bGluZyBwYXRoLCB3aGljaCBkb2VzXG4gICAqIG5vdCBtYXJrIGFuIE9uUHVzaCBjb21wb25lbnQgZGlydHkg4oCUIHdpdGhvdXQgdGhpcyBob29rIHRoZSBjb21wb25lbnQga2VlcHNcbiAgICogcmVuZGVyaW5nIHRoZSBjbGFzcyBpdCB3YXMgYm9ybiB3aXRoLlxuICAgKi9cbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICAvKiogVGV4dCBzaG93biBvbiB0aGUgdHJpZ2dlciB3aGVuIG5vIHRpbWUgaXMgc2VsZWN0ZWQuIEBkZWZhdWx0ICdTZWxlY3QgYSB0aW1lJyAqL1xuICBASW5wdXQoKSBwbGFjZWhvbGRlciA9ICdTZWxlY3QgYSB0aW1lJztcbiAgLyoqIERpc2FibGVzIHRoZSBjb250cm9sLiBAZGVmYXVsdCBmYWxzZSAqL1xuICBASW5wdXQoKSBkaXNhYmxlZCA9IGZhbHNlO1xuICAvKiogUmVuZGVycyBhIDEyLWhvdXIgZmFjZSB3aXRoIGFuIEFNL1BNIGNvbHVtbi4gVGhlIGVtaXR0ZWQgdmFsdWUgc3RheXMgMjQtaG91ci4gQGRlZmF1bHQgZmFsc2UgKi9cbiAgQElucHV0KCkgdXNlMTJIb3VycyA9IGZhbHNlO1xuICAvKiogQWRkcyBhIHNlY29uZHMgY29sdW1uIGFuZCBlbWl0cyBgSEg6bW06c3NgLiBAZGVmYXVsdCBmYWxzZSAqL1xuICBASW5wdXQoKSBzaG93U2Vjb25kcyA9IGZhbHNlO1xuICAvKiogSW50ZXJ2YWwgYmV0d2VlbiBtaW51dGUgZW50cmllcywgaW4gbWludXRlcy4gQGRlZmF1bHQgMSAqL1xuICBASW5wdXQoKSBtaW51dGVTdGVwID0gMTtcbiAgLyoqIEludGVydmFsIGJldHdlZW4gc2Vjb25kIGVudHJpZXMsIGluIHNlY29uZHMuIEBkZWZhdWx0IDEgKi9cbiAgQElucHV0KCkgc2Vjb25kU3RlcCA9IDE7XG4gIC8qKiBFYXJsaWVzdCBzZWxlY3RhYmxlIHRpbWUgYXMgYSAyNC1ob3VyIGBISDptbWAgc3RyaW5nOyBlYXJsaWVyIGVudHJpZXMgYXJlIGRpc2FibGVkLiAqL1xuICBASW5wdXQoKSBtaW4/OiBzdHJpbmc7XG4gIC8qKiBMYXRlc3Qgc2VsZWN0YWJsZSB0aW1lIGFzIGEgMjQtaG91ciBgSEg6bW1gIHN0cmluZzsgbGF0ZXIgZW50cmllcyBhcmUgZGlzYWJsZWQuICovXG4gIEBJbnB1dCgpIG1heD86IHN0cmluZztcbiAgLyoqIEhlaWdodCBhbmQgdGV4dCBzaXplIG9mIHRoZSB0cmlnZ2VyIGFuZCBlbnRyaWVzLiBAZGVmYXVsdCAnZGVmYXVsdCcgKi9cbiAgQElucHV0KCkgc2l6ZTogVGltZVBpY2tlclByb3BzWydzaXplJ10gPSAnZGVmYXVsdCc7XG4gIC8qKiBBcHBsaWVzIHRoZSBkZXN0cnVjdGl2ZSBib3JkZXIgYW5kIGZvY3VzIHJpbmcuIEBkZWZhdWx0IGZhbHNlICovXG4gIEBJbnB1dCgpIGludmFsaWQgPSBmYWxzZTtcbiAgLyoqIEFjY2Vzc2libGUgbmFtZSB3aGVuIHRoZXJlIGlzIG5vIGFzc29jaWF0ZWQgdmlzaWJsZSBsYWJlbC4gQGRlZmF1bHQgJycgKi9cbiAgQElucHV0KCkgYXJpYUxhYmVsID0gJyc7XG4gIC8qKiBFeGNoYW5nZSBgRGF0ZWAgb2JqZWN0cyBpbnN0ZWFkIG9mIGBISDptbWAgc3RyaW5ncyB0aHJvdWdoIHRoZSBmb3JtIGNvbnRyb2wuIEBkZWZhdWx0ICdzdHJpbmcnICovXG4gIEBJbnB1dCgpIHZhbHVlVHlwZTogJ3N0cmluZycgfCAnZGF0ZScgPSAnc3RyaW5nJztcbiAgLyoqIEV4dHJhIFRhaWx3aW5kIGNsYXNzZXMgbWVyZ2VkIG9udG8gdGhlIHRyaWdnZXIgdmlhIGBjbigpYCAobGFzdC13aW5zKS4gKi9cbiAgQElucHV0KCkgY2xhc3MgPSAnJztcblxuICAvKiogRW1pdHRlZCB3aXRoIHRoZSBjaG9zZW4gdGltZSB3aGVuZXZlciBpdCBjaGFuZ2VzLiAqL1xuICBAT3V0cHV0KCkgdmFsdWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZyB8IERhdGUgfCBudWxsPigpO1xuICAvKiogRW1pdHRlZCB3aGVuIHRoZSBwYW5lbCBvcGVucy4gKi9cbiAgQE91dHB1dCgpIG9wZW5lZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgLyoqIEVtaXR0ZWQgd2hlbiB0aGUgcGFuZWwgY2xvc2VzLiAqL1xuICBAT3V0cHV0KCkgY2xvc2VkID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuXG4gIEBWaWV3Q2hpbGQoJ3RyaWdnZXInKSB0cmlnZ2VyRWw/OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcbiAgQFZpZXdDaGlsZCgncGFuZWwnKSBwYW5lbEVsPzogRWxlbWVudFJlZjxIVE1MRWxlbWVudD47XG4gIEBWaWV3Q2hpbGQoJ2NvbHVtbnMnKSBjb2x1bW5zQ21wPzogVGltZUNvbHVtbnNDb21wb25lbnQ7XG5cbiAgcmVhZG9ubHkgcGFuZWxJZCA9ICd0aW1lLXBpY2tlci1wYW5lbC0nICsgTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc2xpY2UoMiwgMTEpO1xuXG4gIGhvdXI6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBtaW51dGU6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBzZWNvbmQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBpc09wZW4gPSBmYWxzZTtcblxuICBwcm90ZWN0ZWQgY24gPSBjbjtcblxuICBwcml2YXRlIGNsZWFudXA/OiAoKSA9PiB2b2lkO1xuICAvKiogVGhlIGRhdGUgaGFsZiBvZiBhIGBEYXRlYCB2YWx1ZSwga2VwdCBzbyByb3VuZC10cmlwcGluZyBkb2VzIG5vdCBtb3ZlIHRoZSBkYXkuICovXG4gIHByaXZhdGUgZGF0ZUFuY2hvcjogRGF0ZSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIG9uQ2hhbmdlOiAodmFsdWU6IHN0cmluZyB8IERhdGUgfCBudWxsKSA9PiB2b2lkID0gKCkgPT4ge307XG4gIHByaXZhdGUgb25Ub3VjaGVkOiAoKSA9PiB2b2lkID0gKCkgPT4ge307XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmKSB7fVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgb3V0c2lkZUNsaWNrSGFuZGxlciA9IChldmVudDogTW91c2VFdmVudCkgPT4ge1xuICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldCBhcyBOb2RlO1xuICAgIGlmIChcbiAgICAgICF0aGlzLnRyaWdnZXJFbD8ubmF0aXZlRWxlbWVudC5jb250YWlucyh0YXJnZXQpICYmXG4gICAgICAhdGhpcy5wYW5lbEVsPy5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKHRhcmdldClcbiAgICApIHtcbiAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICB9XG4gIH07XG5cbiAgcHJpdmF0ZSByZWFkb25seSBlc2NhcGVIYW5kbGVyID0gKGV2ZW50OiBLZXlib2FyZEV2ZW50KSA9PiB7XG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ0VzY2FwZScgJiYgdGhpcy5pc09wZW4pIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB0aGlzLmNsb3NlKCk7XG4gICAgICB0aGlzLnRyaWdnZXJFbD8ubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICAgIH1cbiAgfTtcblxuICAvKiAtLS0tLS0tLS0tLS0tLS0tIGRlcml2ZWQgLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4gIC8qKiBUaGUgY3VycmVudCBzZWxlY3Rpb24gYXMgd2FsbC1jbG9jayBwYXJ0cywgb3IgYG51bGxgIHdoZW4gaW5jb21wbGV0ZS4gKi9cbiAgZ2V0IHBhcnRzKCk6IFRpbWVQYXJ0cyB8IG51bGwge1xuICAgIGlmICh0aGlzLmhvdXIgPT09IG51bGwgfHwgdGhpcy5taW51dGUgPT09IG51bGwpIHJldHVybiBudWxsO1xuICAgIHJldHVybiB7IGhvdXI6IHRoaXMuaG91ciwgbWludXRlOiB0aGlzLm1pbnV0ZSwgc2Vjb25kOiB0aGlzLnNlY29uZCA/PyAwIH07XG4gIH1cblxuICBnZXQgZGlzcGxheVZhbHVlKCk6IHN0cmluZyB7XG4gICAgY29uc3QgcGFydHMgPSB0aGlzLnBhcnRzO1xuICAgIGlmICghcGFydHMpIHJldHVybiAnJztcblxuICAgIGlmICh0aGlzLnVzZTEySG91cnMpIHtcbiAgICAgIGNvbnN0IHsgaG91cjEyLCBtZXJpZGllbSB9ID0gdG8xMkhvdXIocGFydHMuaG91cik7XG4gICAgICBjb25zdCBib2R5ID1cbiAgICAgICAgU3RyaW5nKGhvdXIxMikgK1xuICAgICAgICAnOicgK1xuICAgICAgICBwYWQyKHBhcnRzLm1pbnV0ZSkgK1xuICAgICAgICAodGhpcy5zaG93U2Vjb25kcyA/ICc6JyArIHBhZDIocGFydHMuc2Vjb25kKSA6ICcnKTtcbiAgICAgIHJldHVybiBib2R5ICsgJyAnICsgbWVyaWRpZW07XG4gICAgfVxuICAgIHJldHVybiBmb3JtYXRUaW1lU3RyaW5nKHBhcnRzLCB0aGlzLnNob3dTZWNvbmRzKTtcbiAgfVxuXG4gIGdldCBtaW5TZWNvbmRzKCk6IG51bWJlciB7XG4gICAgY29uc3QgcGFyc2VkID0gcGFyc2VUaW1lU3RyaW5nKHRoaXMubWluKTtcbiAgICByZXR1cm4gcGFyc2VkID8gdGltZVBhcnRzVG9TZWNvbmRzKHBhcnNlZCkgOiAwO1xuICB9XG5cbiAgZ2V0IG1heFNlY29uZHMoKTogbnVtYmVyIHtcbiAgICBjb25zdCBwYXJzZWQgPSBwYXJzZVRpbWVTdHJpbmcodGhpcy5tYXgpO1xuICAgIHJldHVybiBwYXJzZWQgPyB0aW1lUGFydHNUb1NlY29uZHMocGFyc2VkKSA6IFNFQ09ORFNfUEVSX0RBWSAtIDE7XG4gIH1cblxuICBnZXQgY29tcHV0ZWRUcmlnZ2VyQ2xhc3MoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY24odGltZVBpY2tlclRyaWdnZXJWYXJpYW50cyh7IHNpemU6IHRoaXMuc2l6ZSwgaW52YWxpZDogdGhpcy5pbnZhbGlkIH0pLCB0aGlzLmNsYXNzKTtcbiAgfVxuXG4gIC8qIC0tLS0tLS0tLS0tLS0tLS0gb3BlbiAvIGNsb3NlIC0tLS0tLS0tLS0tLS0tLS0gKi9cblxuICB0b2dnbGUoKTogdm9pZCB7XG4gICAgdGhpcy5pc09wZW4gPyB0aGlzLmNsb3NlKCkgOiB0aGlzLm9wZW4oKTtcbiAgfVxuXG4gIG9wZW4oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQgfHwgdGhpcy5pc09wZW4pIHJldHVybjtcbiAgICB0aGlzLmlzT3BlbiA9IHRydWU7XG4gICAgdGhpcy5vcGVuZWQuZW1pdCgpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnVwZGF0ZVBvc2l0aW9uKCk7XG4gICAgICB0aGlzLmNvbHVtbnNDbXA/LnNjcm9sbFNlbGVjdGVkSW50b1ZpZXcoKTtcbiAgICAgIHRoaXMuY29sdW1uc0NtcD8uZm9jdXNGaXJzdENvbHVtbigpO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncG9pbnRlcmRvd24nLCB0aGlzLm91dHNpZGVDbGlja0hhbmRsZXIsIHRydWUpO1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuZXNjYXBlSGFuZGxlciwgdHJ1ZSk7XG4gICAgfSk7XG4gIH1cblxuICBjbG9zZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNPcGVuKSByZXR1cm47XG4gICAgdGhpcy5pc09wZW4gPSBmYWxzZTtcbiAgICB0aGlzLmNsb3NlZC5lbWl0KCk7XG4gICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgICB0aGlzLnRlYXJkb3duKCk7XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBvblRyaWdnZXJLZXlEb3duKGV2ZW50OiBLZXlib2FyZEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKFsnQXJyb3dEb3duJywgJ0Fycm93VXAnLCAnRW50ZXInLCAnICddLmluY2x1ZGVzKGV2ZW50LmtleSkgJiYgIXRoaXMuaXNPcGVuKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgdGhpcy5vcGVuKCk7XG4gICAgfVxuICB9XG5cbiAgLyogLS0tLS0tLS0tLS0tLS0tLSB2YWx1ZSAtLS0tLS0tLS0tLS0tLS0tICovXG5cbiAgb25UaW1lQ2hhbmdlKHBhcnRzOiBUaW1lUGFydHMpOiB2b2lkIHtcbiAgICB0aGlzLmhvdXIgPSBwYXJ0cy5ob3VyO1xuICAgIHRoaXMubWludXRlID0gcGFydHMubWludXRlO1xuICAgIHRoaXMuc2Vjb25kID0gcGFydHMuc2Vjb25kO1xuICAgIHRoaXMuZW1pdCgpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgcHJpdmF0ZSBlbWl0KCk6IHZvaWQge1xuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5jdXJyZW50VmFsdWUoKTtcbiAgICB0aGlzLm9uQ2hhbmdlKHZhbHVlKTtcbiAgICB0aGlzLnZhbHVlQ2hhbmdlLmVtaXQodmFsdWUpO1xuICB9XG5cbiAgcHJpdmF0ZSBjdXJyZW50VmFsdWUoKTogc3RyaW5nIHwgRGF0ZSB8IG51bGwge1xuICAgIGNvbnN0IHBhcnRzID0gdGhpcy5wYXJ0cztcbiAgICBpZiAoIXBhcnRzKSByZXR1cm4gbnVsbDtcbiAgICBpZiAodGhpcy52YWx1ZVR5cGUgPT09ICdkYXRlJykge1xuICAgICAgY29uc3QgYmFzZSA9IHRoaXMuZGF0ZUFuY2hvciA/PyBuZXcgRGF0ZSgpO1xuICAgICAgcmV0dXJuIG5ldyBEYXRlKFxuICAgICAgICBiYXNlLmdldEZ1bGxZZWFyKCksXG4gICAgICAgIGJhc2UuZ2V0TW9udGgoKSxcbiAgICAgICAgYmFzZS5nZXREYXRlKCksXG4gICAgICAgIHBhcnRzLmhvdXIsXG4gICAgICAgIHBhcnRzLm1pbnV0ZSxcbiAgICAgICAgcGFydHMuc2Vjb25kLFxuICAgICAgICAwXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gZm9ybWF0VGltZVN0cmluZyhwYXJ0cywgdGhpcy5zaG93U2Vjb25kcyk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVBvc2l0aW9uKCk6IHZvaWQge1xuICAgIGNvbnN0IHRyaWdnZXIgPSB0aGlzLnRyaWdnZXJFbD8ubmF0aXZlRWxlbWVudDtcbiAgICBjb25zdCBwYW5lbCA9IHRoaXMucGFuZWxFbD8ubmF0aXZlRWxlbWVudDtcbiAgICBpZiAoIXRyaWdnZXIgfHwgIXBhbmVsKSByZXR1cm47XG5cbiAgICB0aGlzLmNsZWFudXAgPSBhdXRvVXBkYXRlKHRyaWdnZXIsIHBhbmVsLCAoKSA9PiB7XG4gICAgICBjb21wdXRlUG9zaXRpb24odHJpZ2dlciwgcGFuZWwsIHtcbiAgICAgICAgc3RyYXRlZ3k6ICdmaXhlZCcsXG4gICAgICAgIHBsYWNlbWVudDogJ2JvdHRvbS1zdGFydCcsXG4gICAgICAgIG1pZGRsZXdhcmU6IFtvZmZzZXQoNCksIGZsaXAoKSwgc2hpZnQoeyBwYWRkaW5nOiA4IH0pXSxcbiAgICAgIH0pLnRoZW4oKHsgeCwgeSB9KSA9PiB7XG4gICAgICAgIE9iamVjdC5hc3NpZ24ocGFuZWwuc3R5bGUsIHtcbiAgICAgICAgICBsZWZ0OiB4ICsgJ3B4JyxcbiAgICAgICAgICB0b3A6IHkgKyAncHgnLFxuICAgICAgICAgIHZpc2liaWxpdHk6ICd2aXNpYmxlJyxcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgdGVhcmRvd24oKTogdm9pZCB7XG4gICAgdGhpcy5jbGVhbnVwPy4oKTtcbiAgICB0aGlzLmNsZWFudXAgPSB1bmRlZmluZWQ7XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncG9pbnRlcmRvd24nLCB0aGlzLm91dHNpZGVDbGlja0hhbmRsZXIsIHRydWUpO1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLmVzY2FwZUhhbmRsZXIsIHRydWUpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy50ZWFyZG93bigpO1xuICB9XG5cbiAgLyogLS0tLS0tLS0tLS0tLS0tLSBDb250cm9sVmFsdWVBY2Nlc3NvciAtLS0tLS0tLS0tLS0tLS0tICovXG5cbiAgd3JpdGVWYWx1ZSh2YWx1ZTogc3RyaW5nIHwgRGF0ZSB8IG51bGwgfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgICBsZXQgcGFydHM6IFRpbWVQYXJ0cyB8IG51bGwgPSBudWxsO1xuXG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSAmJiAhaXNOYU4odmFsdWUuZ2V0VGltZSgpKSkge1xuICAgICAgdGhpcy5kYXRlQW5jaG9yID0gdmFsdWU7XG4gICAgICBwYXJ0cyA9IHsgaG91cjogdmFsdWUuZ2V0SG91cnMoKSwgbWludXRlOiB2YWx1ZS5nZXRNaW51dGVzKCksIHNlY29uZDogdmFsdWUuZ2V0U2Vjb25kcygpIH07XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICBwYXJ0cyA9IHBhcnNlVGltZVN0cmluZyh2YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhpcy5ob3VyID0gcGFydHMgPyBwYXJ0cy5ob3VyIDogbnVsbDtcbiAgICB0aGlzLm1pbnV0ZSA9IHBhcnRzID8gcGFydHMubWludXRlIDogbnVsbDtcbiAgICB0aGlzLnNlY29uZCA9IHBhcnRzID8gcGFydHMuc2Vjb25kIDogbnVsbDtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46ICh2YWx1ZTogc3RyaW5nIHwgRGF0ZSB8IG51bGwpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLm9uQ2hhbmdlID0gZm47XG4gIH1cblxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogKCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMub25Ub3VjaGVkID0gZm47XG4gIH1cblxuICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLmRpc2FibGVkID0gaXNEaXNhYmxlZDtcbiAgICBpZiAoaXNEaXNhYmxlZCkgdGhpcy5jbG9zZSgpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG59XG4iXX0=
|