@tolle_/tolle-ui 18.2.29 → 18.3.0
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 +12 -12
- package/esm2022/lib/alert-dialog.component.mjs +82 -64
- package/esm2022/lib/alert-dialog.service.mjs +38 -6
- 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 +125 -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/modal-ref.mjs +36 -7
- package/esm2022/lib/modal.component.mjs +42 -28
- package/esm2022/lib/modal.mjs +2 -29
- package/esm2022/lib/modal.service.mjs +26 -4
- 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-panel.component.mjs +5 -5
- package/esm2022/lib/resizable.component.mjs +219 -0
- package/esm2022/lib/segment.component.mjs +19 -9
- 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 +16642 -1105
- package/fesm2022/tolle-ui.mjs.map +1 -1
- package/lib/alert-dialog-dynamic.component.d.ts +5 -0
- package/lib/alert-dialog.component.d.ts +23 -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/modal-ref.d.ts +6 -1
- package/lib/modal.component.d.ts +7 -4
- package/lib/modal.d.ts +9 -3
- 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 +3 -2
- package/preset.js +7 -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-menu-trigger.json +1 -1
- package/registry/r/context-menu.json +1 -1
- 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/modal.json +3 -3
- 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/resizable-panel.json +1 -1
- 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 +121 -8
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter, forwardRef, ViewChild, ChangeDetectionStrategy } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms';
|
|
4
|
+
import { computePosition, flip, shift, offset, autoUpdate } from '@floating-ui/dom';
|
|
5
|
+
import { cva } from 'class-variance-authority';
|
|
6
|
+
import { format, isSameDay, isValid, startOfDay } from 'date-fns';
|
|
7
|
+
import { cn } from './utils/cn';
|
|
8
|
+
import { CalendarComponent } from './calendar.component';
|
|
9
|
+
import { TimeColumnsComponent, to12Hour } from './time-picker.component';
|
|
10
|
+
import * as i0 from "@angular/core";
|
|
11
|
+
import * as i1 from "@angular/common";
|
|
12
|
+
import * as i2 from "@angular/forms";
|
|
13
|
+
const SECONDS_PER_DAY = 24 * 3600;
|
|
14
|
+
const dateTimePickerTriggerVariants = cva('flex w-full items-center justify-between gap-2 rounded-md border border-input bg-background text-foreground shadow-sm transition-colors ' +
|
|
15
|
+
'focus:outline-none focus-visible:border-primary/80 focus-visible:ring-4 focus-visible:ring-ring/30 ' +
|
|
16
|
+
'disabled:cursor-not-allowed disabled:opacity-50', {
|
|
17
|
+
variants: {
|
|
18
|
+
size: {
|
|
19
|
+
xs: 'h-8 px-2 text-xs',
|
|
20
|
+
sm: 'h-9 px-3 text-sm',
|
|
21
|
+
default: 'h-10 px-3 text-sm',
|
|
22
|
+
lg: 'h-11 px-4 text-base',
|
|
23
|
+
},
|
|
24
|
+
invalid: {
|
|
25
|
+
true: 'border-destructive focus-visible:border-destructive/80 focus-visible:ring-destructive/30',
|
|
26
|
+
false: '',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: { size: 'default', invalid: false },
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* One control for a date *and* a time: `tolle-calendar` on the left, the
|
|
33
|
+
* `tolle-time-columns` strip on the right, in a single floating panel with a
|
|
34
|
+
* Clear / Done footer.
|
|
35
|
+
*
|
|
36
|
+
* The value is a `Date`, because a date-time genuinely is a moment. Changing
|
|
37
|
+
* the date preserves the chosen time and changing the time preserves the
|
|
38
|
+
* chosen date — the two halves are only ever recombined, never reset.
|
|
39
|
+
*
|
|
40
|
+
* Implements `ControlValueAccessor`, so it works with `ngModel` and reactive
|
|
41
|
+
* forms. Use `tolle-date-picker` for a date alone and `tolle-time-picker` for a
|
|
42
|
+
* time alone.
|
|
43
|
+
* @new
|
|
44
|
+
*/
|
|
45
|
+
export class DateTimePickerComponent {
|
|
46
|
+
cdr;
|
|
47
|
+
/** Text shown on the trigger when nothing is selected. @default 'Select date and time' */
|
|
48
|
+
placeholder = 'Select date and time';
|
|
49
|
+
/** Disables the control. @default false */
|
|
50
|
+
disabled = false;
|
|
51
|
+
/** Renders a 12-hour face with an AM/PM column. @default false */
|
|
52
|
+
use12Hours = false;
|
|
53
|
+
/** Adds a seconds column. @default false */
|
|
54
|
+
showSeconds = false;
|
|
55
|
+
/** Interval between minute entries, in minutes. @default 1 */
|
|
56
|
+
minuteStep = 1;
|
|
57
|
+
/** Earliest selectable moment; earlier days and times are disabled. */
|
|
58
|
+
min;
|
|
59
|
+
/** Latest selectable moment; later days and times are disabled. */
|
|
60
|
+
max;
|
|
61
|
+
/** date-fns pattern used to render the value on the trigger. @default 'MMM d, yyyy h:mm a' */
|
|
62
|
+
displayFormat = 'MMM d, yyyy h:mm a';
|
|
63
|
+
/** Height and text size of the trigger and entries. @default 'default' */
|
|
64
|
+
size = 'default';
|
|
65
|
+
/** Applies the destructive border and focus ring. @default false */
|
|
66
|
+
invalid = false;
|
|
67
|
+
/** Accessible name when there is no associated visible label. @default '' */
|
|
68
|
+
ariaLabel = '';
|
|
69
|
+
/** Extra Tailwind classes merged onto the trigger via `cn()` (last-wins). */
|
|
70
|
+
class = '';
|
|
71
|
+
/** Emitted with the chosen moment, or `null` when the value is cleared. */
|
|
72
|
+
valueChange = new EventEmitter();
|
|
73
|
+
/** Emitted when the panel opens. */
|
|
74
|
+
opened = new EventEmitter();
|
|
75
|
+
/** Emitted when the panel closes. */
|
|
76
|
+
closed = new EventEmitter();
|
|
77
|
+
triggerEl;
|
|
78
|
+
panelEl;
|
|
79
|
+
columnsCmp;
|
|
80
|
+
panelId = 'date-time-picker-panel-' + Math.random().toString(36).slice(2, 11);
|
|
81
|
+
value = null;
|
|
82
|
+
isOpen = false;
|
|
83
|
+
/**
|
|
84
|
+
* Day-only copies of `min` / `max` for the calendar. The calendar compares
|
|
85
|
+
* whole `Date`s, so passing a bound that carries a time would disable its own
|
|
86
|
+
* day — 09:00 on the min day would look "before" a 09:30 minimum.
|
|
87
|
+
*/
|
|
88
|
+
calendarMin;
|
|
89
|
+
calendarMax;
|
|
90
|
+
footerButtonClass = cn('rounded-md px-3 py-1.5 text-sm font-medium text-muted-foreground transition-colors', 'hover:bg-accent hover:text-accent-foreground', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring');
|
|
91
|
+
cn = cn;
|
|
92
|
+
cleanup;
|
|
93
|
+
onChange = () => { };
|
|
94
|
+
onTouched = () => { };
|
|
95
|
+
constructor(cdr) {
|
|
96
|
+
this.cdr = cdr;
|
|
97
|
+
}
|
|
98
|
+
ngOnChanges() {
|
|
99
|
+
this.calendarMin = this.min ? startOfDay(this.min) : undefined;
|
|
100
|
+
this.calendarMax = this.max ? startOfDay(this.max) : undefined;
|
|
101
|
+
// A bound `class` input is written through Angular's styling path,
|
|
102
|
+
// which does not mark an OnPush view dirty on its own.
|
|
103
|
+
this.cdr.markForCheck();
|
|
104
|
+
}
|
|
105
|
+
outsideClickHandler = (event) => {
|
|
106
|
+
const target = event.target;
|
|
107
|
+
if (!this.triggerEl?.nativeElement.contains(target) &&
|
|
108
|
+
!this.panelEl?.nativeElement.contains(target)) {
|
|
109
|
+
this.close();
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
escapeHandler = (event) => {
|
|
113
|
+
if (event.key === 'Escape' && this.isOpen) {
|
|
114
|
+
event.preventDefault();
|
|
115
|
+
this.close();
|
|
116
|
+
this.triggerEl?.nativeElement.focus();
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
/* ---------------- derived ---------------- */
|
|
120
|
+
get hour() {
|
|
121
|
+
return this.value ? this.value.getHours() : null;
|
|
122
|
+
}
|
|
123
|
+
get minute() {
|
|
124
|
+
return this.value ? this.value.getMinutes() : null;
|
|
125
|
+
}
|
|
126
|
+
get second() {
|
|
127
|
+
return this.value ? this.value.getSeconds() : null;
|
|
128
|
+
}
|
|
129
|
+
get displayValue() {
|
|
130
|
+
if (!this.value)
|
|
131
|
+
return '';
|
|
132
|
+
try {
|
|
133
|
+
return format(this.value, this.displayFormat);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// A bad pattern should not blank the control; fall back to something readable.
|
|
137
|
+
const { hour12, meridiem } = to12Hour(this.value.getHours());
|
|
138
|
+
return (format(this.value, 'MMM d, yyyy') +
|
|
139
|
+
' ' +
|
|
140
|
+
hour12 +
|
|
141
|
+
':' +
|
|
142
|
+
String(this.value.getMinutes()).padStart(2, '0') +
|
|
143
|
+
' ' +
|
|
144
|
+
meridiem);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The time bound only bites on the boundary day itself: on the min day the
|
|
149
|
+
* columns start at the min time, on any later day they start at midnight.
|
|
150
|
+
*/
|
|
151
|
+
get minSeconds() {
|
|
152
|
+
if (!this.min)
|
|
153
|
+
return 0;
|
|
154
|
+
const day = this.value ?? this.min;
|
|
155
|
+
if (!isSameDay(day, this.min))
|
|
156
|
+
return 0;
|
|
157
|
+
return this.min.getHours() * 3600 + this.min.getMinutes() * 60 + this.min.getSeconds();
|
|
158
|
+
}
|
|
159
|
+
get maxSeconds() {
|
|
160
|
+
if (!this.max)
|
|
161
|
+
return SECONDS_PER_DAY - 1;
|
|
162
|
+
const day = this.value ?? this.max;
|
|
163
|
+
if (!isSameDay(day, this.max))
|
|
164
|
+
return SECONDS_PER_DAY - 1;
|
|
165
|
+
return this.max.getHours() * 3600 + this.max.getMinutes() * 60 + this.max.getSeconds();
|
|
166
|
+
}
|
|
167
|
+
get computedTriggerClass() {
|
|
168
|
+
return cn(dateTimePickerTriggerVariants({ size: this.size, invalid: this.invalid }), this.class);
|
|
169
|
+
}
|
|
170
|
+
/* ---------------- open / close ---------------- */
|
|
171
|
+
toggle() {
|
|
172
|
+
this.isOpen ? this.close() : this.open();
|
|
173
|
+
}
|
|
174
|
+
open() {
|
|
175
|
+
if (this.disabled || this.isOpen)
|
|
176
|
+
return;
|
|
177
|
+
this.isOpen = true;
|
|
178
|
+
this.opened.emit();
|
|
179
|
+
this.cdr.markForCheck();
|
|
180
|
+
setTimeout(() => {
|
|
181
|
+
this.updatePosition();
|
|
182
|
+
this.columnsCmp?.scrollSelectedIntoView();
|
|
183
|
+
document.addEventListener('pointerdown', this.outsideClickHandler, true);
|
|
184
|
+
document.addEventListener('keydown', this.escapeHandler, true);
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
close() {
|
|
188
|
+
if (!this.isOpen)
|
|
189
|
+
return;
|
|
190
|
+
this.isOpen = false;
|
|
191
|
+
this.closed.emit();
|
|
192
|
+
this.onTouched();
|
|
193
|
+
this.teardown();
|
|
194
|
+
this.cdr.markForCheck();
|
|
195
|
+
}
|
|
196
|
+
onTriggerKeyDown(event) {
|
|
197
|
+
if (['ArrowDown', 'ArrowUp', 'Enter', ' '].includes(event.key) && !this.isOpen) {
|
|
198
|
+
event.preventDefault();
|
|
199
|
+
this.open();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/* ---------------- value ---------------- */
|
|
203
|
+
/**
|
|
204
|
+
* Applies a newly picked day, carrying the existing time across. With no
|
|
205
|
+
* time chosen yet the day starts at midnight.
|
|
206
|
+
*/
|
|
207
|
+
onDateSelect(date) {
|
|
208
|
+
if (!date) {
|
|
209
|
+
this.clear();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const previous = this.value;
|
|
213
|
+
this.commit(new Date(date.getFullYear(), date.getMonth(), date.getDate(), previous ? previous.getHours() : 0, previous ? previous.getMinutes() : 0, previous ? previous.getSeconds() : 0, 0));
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Applies a newly picked time, carrying the existing day across. With no day
|
|
217
|
+
* chosen yet the time lands on today.
|
|
218
|
+
*/
|
|
219
|
+
onTimeChange(parts) {
|
|
220
|
+
const base = this.value ?? new Date();
|
|
221
|
+
this.commit(new Date(base.getFullYear(), base.getMonth(), base.getDate(), parts.hour, parts.minute, parts.second, 0));
|
|
222
|
+
}
|
|
223
|
+
clear() {
|
|
224
|
+
this.commit(null);
|
|
225
|
+
// The calendar keeps its own selection and ignores a null written through
|
|
226
|
+
// the CVA, so closing is what actually returns it to a clean state — it is
|
|
227
|
+
// rebuilt from scratch the next time the panel opens.
|
|
228
|
+
this.close();
|
|
229
|
+
}
|
|
230
|
+
done() {
|
|
231
|
+
this.close();
|
|
232
|
+
this.triggerEl?.nativeElement.focus();
|
|
233
|
+
}
|
|
234
|
+
commit(next) {
|
|
235
|
+
this.value = next;
|
|
236
|
+
this.onChange(next);
|
|
237
|
+
this.valueChange.emit(next);
|
|
238
|
+
this.cdr.markForCheck();
|
|
239
|
+
}
|
|
240
|
+
updatePosition() {
|
|
241
|
+
const trigger = this.triggerEl?.nativeElement;
|
|
242
|
+
const panel = this.panelEl?.nativeElement;
|
|
243
|
+
if (!trigger || !panel)
|
|
244
|
+
return;
|
|
245
|
+
this.cleanup = autoUpdate(trigger, panel, () => {
|
|
246
|
+
computePosition(trigger, panel, {
|
|
247
|
+
strategy: 'fixed',
|
|
248
|
+
placement: 'bottom-start',
|
|
249
|
+
middleware: [offset(4), flip(), shift({ padding: 8 })],
|
|
250
|
+
}).then(({ x, y }) => {
|
|
251
|
+
Object.assign(panel.style, {
|
|
252
|
+
left: x + 'px',
|
|
253
|
+
top: y + 'px',
|
|
254
|
+
visibility: 'visible',
|
|
255
|
+
});
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
teardown() {
|
|
260
|
+
this.cleanup?.();
|
|
261
|
+
this.cleanup = undefined;
|
|
262
|
+
document.removeEventListener('pointerdown', this.outsideClickHandler, true);
|
|
263
|
+
document.removeEventListener('keydown', this.escapeHandler, true);
|
|
264
|
+
}
|
|
265
|
+
ngOnDestroy() {
|
|
266
|
+
this.teardown();
|
|
267
|
+
}
|
|
268
|
+
/* ---------------- ControlValueAccessor ---------------- */
|
|
269
|
+
writeValue(value) {
|
|
270
|
+
if (value instanceof Date && isValid(value)) {
|
|
271
|
+
this.value = value;
|
|
272
|
+
}
|
|
273
|
+
else if (typeof value === 'string' && value) {
|
|
274
|
+
const parsed = new Date(value);
|
|
275
|
+
this.value = isValid(parsed) ? parsed : null;
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
this.value = null;
|
|
279
|
+
}
|
|
280
|
+
this.cdr.markForCheck();
|
|
281
|
+
}
|
|
282
|
+
registerOnChange(fn) {
|
|
283
|
+
this.onChange = fn;
|
|
284
|
+
}
|
|
285
|
+
registerOnTouched(fn) {
|
|
286
|
+
this.onTouched = fn;
|
|
287
|
+
}
|
|
288
|
+
setDisabledState(isDisabled) {
|
|
289
|
+
this.disabled = isDisabled;
|
|
290
|
+
if (isDisabled)
|
|
291
|
+
this.close();
|
|
292
|
+
this.cdr.markForCheck();
|
|
293
|
+
}
|
|
294
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DateTimePickerComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
295
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: DateTimePickerComponent, isStandalone: true, selector: "tolle-date-time-picker", inputs: { placeholder: "placeholder", disabled: "disabled", use12Hours: "use12Hours", showSeconds: "showSeconds", minuteStep: "minuteStep", min: "min", max: "max", displayFormat: "displayFormat", size: "size", invalid: "invalid", ariaLabel: "ariaLabel", class: "class" }, outputs: { valueChange: "valueChange", opened: "opened", closed: "closed" }, providers: [
|
|
296
|
+
{
|
|
297
|
+
provide: NG_VALUE_ACCESSOR,
|
|
298
|
+
useExisting: forwardRef(() => DateTimePickerComponent),
|
|
299
|
+
multi: true,
|
|
300
|
+
},
|
|
301
|
+
], 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: `
|
|
302
|
+
<button
|
|
303
|
+
#trigger
|
|
304
|
+
type="button"
|
|
305
|
+
aria-haspopup="dialog"
|
|
306
|
+
[attr.aria-expanded]="isOpen"
|
|
307
|
+
[attr.aria-controls]="isOpen ? panelId : null"
|
|
308
|
+
[attr.aria-label]="ariaLabel || null"
|
|
309
|
+
[attr.data-state]="isOpen ? 'open' : 'closed'"
|
|
310
|
+
[disabled]="disabled"
|
|
311
|
+
[class]="computedTriggerClass"
|
|
312
|
+
(click)="toggle()"
|
|
313
|
+
(keydown)="onTriggerKeyDown($event)"
|
|
314
|
+
>
|
|
315
|
+
<span [class]="cn('truncate', displayValue ? 'text-foreground' : 'text-muted-foreground')">
|
|
316
|
+
{{ displayValue || placeholder }}
|
|
317
|
+
</span>
|
|
318
|
+
<i class="ri-calendar-schedule-line shrink-0 text-muted-foreground" aria-hidden="true"></i>
|
|
319
|
+
</button>
|
|
320
|
+
|
|
321
|
+
<div
|
|
322
|
+
*ngIf="isOpen"
|
|
323
|
+
#panel
|
|
324
|
+
role="dialog"
|
|
325
|
+
[id]="panelId"
|
|
326
|
+
[attr.aria-label]="ariaLabel || 'Choose a date and time'"
|
|
327
|
+
class="fixed left-0 top-0 z-[9999]"
|
|
328
|
+
style="visibility: hidden"
|
|
329
|
+
>
|
|
330
|
+
<div class="rounded-md border border-border bg-popover text-popover-foreground shadow-md">
|
|
331
|
+
<div class="flex flex-col sm:flex-row">
|
|
332
|
+
<div class="p-3">
|
|
333
|
+
<tolle-calendar
|
|
334
|
+
[bordered]="false"
|
|
335
|
+
[showQuickActions]="false"
|
|
336
|
+
[minDate]="calendarMin"
|
|
337
|
+
[maxDate]="calendarMax"
|
|
338
|
+
[ngModel]="value"
|
|
339
|
+
(dateSelect)="onDateSelect($event)"
|
|
340
|
+
></tolle-calendar>
|
|
341
|
+
</div>
|
|
342
|
+
|
|
343
|
+
<div class="border-t border-border p-3 sm:border-l sm:border-t-0">
|
|
344
|
+
<tolle-time-columns
|
|
345
|
+
#columns
|
|
346
|
+
[hour]="hour"
|
|
347
|
+
[minute]="minute"
|
|
348
|
+
[second]="second"
|
|
349
|
+
[use12Hours]="use12Hours"
|
|
350
|
+
[showSeconds]="showSeconds"
|
|
351
|
+
[minuteStep]="minuteStep"
|
|
352
|
+
[minSeconds]="minSeconds"
|
|
353
|
+
[maxSeconds]="maxSeconds"
|
|
354
|
+
[size]="size"
|
|
355
|
+
(timeChange)="onTimeChange($event)"
|
|
356
|
+
></tolle-time-columns>
|
|
357
|
+
</div>
|
|
358
|
+
</div>
|
|
359
|
+
|
|
360
|
+
<div class="flex items-center justify-between gap-2 border-t border-border px-3 py-2">
|
|
361
|
+
<button
|
|
362
|
+
type="button"
|
|
363
|
+
[class]="footerButtonClass"
|
|
364
|
+
(click)="clear()"
|
|
365
|
+
>
|
|
366
|
+
Clear
|
|
367
|
+
</button>
|
|
368
|
+
<button
|
|
369
|
+
type="button"
|
|
370
|
+
[class]="cn(footerButtonClass, 'bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground')"
|
|
371
|
+
(click)="done()"
|
|
372
|
+
>
|
|
373
|
+
Done
|
|
374
|
+
</button>
|
|
375
|
+
</div>
|
|
376
|
+
</div>
|
|
377
|
+
</div>
|
|
378
|
+
`, isInline: true, styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: CalendarComponent, selector: "tolle-calendar", inputs: ["class", "bordered", "mode", "disablePastDates", "showQuickActions", "minDate", "maxDate", "formatMonthFn", "formatYearFn", "formatDateFn"], outputs: ["dateSelect"] }, { 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 });
|
|
379
|
+
}
|
|
380
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DateTimePickerComponent, decorators: [{
|
|
381
|
+
type: Component,
|
|
382
|
+
args: [{ selector: 'tolle-date-time-picker', standalone: true, imports: [CommonModule, FormsModule, CalendarComponent, TimeColumnsComponent], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
383
|
+
{
|
|
384
|
+
provide: NG_VALUE_ACCESSOR,
|
|
385
|
+
useExisting: forwardRef(() => DateTimePickerComponent),
|
|
386
|
+
multi: true,
|
|
387
|
+
},
|
|
388
|
+
], template: `
|
|
389
|
+
<button
|
|
390
|
+
#trigger
|
|
391
|
+
type="button"
|
|
392
|
+
aria-haspopup="dialog"
|
|
393
|
+
[attr.aria-expanded]="isOpen"
|
|
394
|
+
[attr.aria-controls]="isOpen ? panelId : null"
|
|
395
|
+
[attr.aria-label]="ariaLabel || null"
|
|
396
|
+
[attr.data-state]="isOpen ? 'open' : 'closed'"
|
|
397
|
+
[disabled]="disabled"
|
|
398
|
+
[class]="computedTriggerClass"
|
|
399
|
+
(click)="toggle()"
|
|
400
|
+
(keydown)="onTriggerKeyDown($event)"
|
|
401
|
+
>
|
|
402
|
+
<span [class]="cn('truncate', displayValue ? 'text-foreground' : 'text-muted-foreground')">
|
|
403
|
+
{{ displayValue || placeholder }}
|
|
404
|
+
</span>
|
|
405
|
+
<i class="ri-calendar-schedule-line shrink-0 text-muted-foreground" aria-hidden="true"></i>
|
|
406
|
+
</button>
|
|
407
|
+
|
|
408
|
+
<div
|
|
409
|
+
*ngIf="isOpen"
|
|
410
|
+
#panel
|
|
411
|
+
role="dialog"
|
|
412
|
+
[id]="panelId"
|
|
413
|
+
[attr.aria-label]="ariaLabel || 'Choose a date and time'"
|
|
414
|
+
class="fixed left-0 top-0 z-[9999]"
|
|
415
|
+
style="visibility: hidden"
|
|
416
|
+
>
|
|
417
|
+
<div class="rounded-md border border-border bg-popover text-popover-foreground shadow-md">
|
|
418
|
+
<div class="flex flex-col sm:flex-row">
|
|
419
|
+
<div class="p-3">
|
|
420
|
+
<tolle-calendar
|
|
421
|
+
[bordered]="false"
|
|
422
|
+
[showQuickActions]="false"
|
|
423
|
+
[minDate]="calendarMin"
|
|
424
|
+
[maxDate]="calendarMax"
|
|
425
|
+
[ngModel]="value"
|
|
426
|
+
(dateSelect)="onDateSelect($event)"
|
|
427
|
+
></tolle-calendar>
|
|
428
|
+
</div>
|
|
429
|
+
|
|
430
|
+
<div class="border-t border-border p-3 sm:border-l sm:border-t-0">
|
|
431
|
+
<tolle-time-columns
|
|
432
|
+
#columns
|
|
433
|
+
[hour]="hour"
|
|
434
|
+
[minute]="minute"
|
|
435
|
+
[second]="second"
|
|
436
|
+
[use12Hours]="use12Hours"
|
|
437
|
+
[showSeconds]="showSeconds"
|
|
438
|
+
[minuteStep]="minuteStep"
|
|
439
|
+
[minSeconds]="minSeconds"
|
|
440
|
+
[maxSeconds]="maxSeconds"
|
|
441
|
+
[size]="size"
|
|
442
|
+
(timeChange)="onTimeChange($event)"
|
|
443
|
+
></tolle-time-columns>
|
|
444
|
+
</div>
|
|
445
|
+
</div>
|
|
446
|
+
|
|
447
|
+
<div class="flex items-center justify-between gap-2 border-t border-border px-3 py-2">
|
|
448
|
+
<button
|
|
449
|
+
type="button"
|
|
450
|
+
[class]="footerButtonClass"
|
|
451
|
+
(click)="clear()"
|
|
452
|
+
>
|
|
453
|
+
Clear
|
|
454
|
+
</button>
|
|
455
|
+
<button
|
|
456
|
+
type="button"
|
|
457
|
+
[class]="cn(footerButtonClass, 'bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground')"
|
|
458
|
+
(click)="done()"
|
|
459
|
+
>
|
|
460
|
+
Done
|
|
461
|
+
</button>
|
|
462
|
+
</div>
|
|
463
|
+
</div>
|
|
464
|
+
</div>
|
|
465
|
+
`, styles: [":host{display:block}\n"] }]
|
|
466
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { placeholder: [{
|
|
467
|
+
type: Input
|
|
468
|
+
}], disabled: [{
|
|
469
|
+
type: Input
|
|
470
|
+
}], use12Hours: [{
|
|
471
|
+
type: Input
|
|
472
|
+
}], showSeconds: [{
|
|
473
|
+
type: Input
|
|
474
|
+
}], minuteStep: [{
|
|
475
|
+
type: Input
|
|
476
|
+
}], min: [{
|
|
477
|
+
type: Input
|
|
478
|
+
}], max: [{
|
|
479
|
+
type: Input
|
|
480
|
+
}], displayFormat: [{
|
|
481
|
+
type: Input
|
|
482
|
+
}], size: [{
|
|
483
|
+
type: Input
|
|
484
|
+
}], invalid: [{
|
|
485
|
+
type: Input
|
|
486
|
+
}], ariaLabel: [{
|
|
487
|
+
type: Input
|
|
488
|
+
}], class: [{
|
|
489
|
+
type: Input
|
|
490
|
+
}], valueChange: [{
|
|
491
|
+
type: Output
|
|
492
|
+
}], opened: [{
|
|
493
|
+
type: Output
|
|
494
|
+
}], closed: [{
|
|
495
|
+
type: Output
|
|
496
|
+
}], triggerEl: [{
|
|
497
|
+
type: ViewChild,
|
|
498
|
+
args: ['trigger']
|
|
499
|
+
}], panelEl: [{
|
|
500
|
+
type: ViewChild,
|
|
501
|
+
args: ['panel']
|
|
502
|
+
}], columnsCmp: [{
|
|
503
|
+
type: ViewChild,
|
|
504
|
+
args: ['columns']
|
|
505
|
+
}] } });
|
|
506
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy90b2xsZS9zcmMvbGliL2RhdGUtdGltZS1waWNrZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFjLFNBQVMsRUFBcUIsdUJBQXVCLEVBQWdDLE1BQU0sZUFBZSxDQUFDO0FBQ3BMLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQXdCLGlCQUFpQixFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3RGLE9BQU8sRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDcEYsT0FBTyxFQUFFLEdBQUcsRUFBcUIsTUFBTSwwQkFBMEIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDaEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDekQsT0FBTyxFQUFFLG9CQUFvQixFQUFhLFFBQVEsRUFBRSxNQUFNLHlCQUF5QixDQUFDOzs7O0FBRXBGLE1BQU0sZUFBZSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFFbEMsTUFBTSw2QkFBNkIsR0FBRyxHQUFHLENBQ3ZDLDBJQUEwSTtJQUN4SSxxR0FBcUc7SUFDckcsaURBQWlELEVBQ25EO0lBQ0UsUUFBUSxFQUFFO1FBQ1IsSUFBSSxFQUFFO1lBQ0osRUFBRSxFQUFFLGtCQUFrQjtZQUN0QixFQUFFLEVBQUUsa0JBQWtCO1lBQ3RCLE9BQU8sRUFBRSxtQkFBbUI7WUFDNUIsRUFBRSxFQUFFLHFCQUFxQjtTQUMxQjtRQUNELE9BQU8sRUFBRTtZQUNQLElBQUksRUFBRSwwRkFBMEY7WUFDaEcsS0FBSyxFQUFFLEVBQUU7U0FDVjtLQUNGO0lBQ0QsZUFBZSxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFO0NBQ3JELENBQ0YsQ0FBQztBQUtGOzs7Ozs7Ozs7Ozs7O0dBYUc7QUE2RkgsTUFBTSxPQUFPLHVCQUF1QjtJQThEZDtJQTdEcEIsMEZBQTBGO0lBQ2pGLFdBQVcsR0FBRyxzQkFBc0IsQ0FBQztJQUM5QywyQ0FBMkM7SUFDbEMsUUFBUSxHQUFHLEtBQUssQ0FBQztJQUMxQixrRUFBa0U7SUFDekQsVUFBVSxHQUFHLEtBQUssQ0FBQztJQUM1Qiw0Q0FBNEM7SUFDbkMsV0FBVyxHQUFHLEtBQUssQ0FBQztJQUM3Qiw4REFBOEQ7SUFDckQsVUFBVSxHQUFHLENBQUMsQ0FBQztJQUN4Qix1RUFBdUU7SUFDOUQsR0FBRyxDQUFRO0lBQ3BCLG1FQUFtRTtJQUMxRCxHQUFHLENBQVE7SUFDcEIsOEZBQThGO0lBQ3JGLGFBQWEsR0FBRyxvQkFBb0IsQ0FBQztJQUM5QywwRUFBMEU7SUFDakUsSUFBSSxHQUFnQyxTQUFTLENBQUM7SUFDdkQsb0VBQW9FO0lBQzNELE9BQU8sR0FBRyxLQUFLLENBQUM7SUFDekIsNkVBQTZFO0lBQ3BFLFNBQVMsR0FBRyxFQUFFLENBQUM7SUFDeEIsNkVBQTZFO0lBQ3BFLEtBQUssR0FBRyxFQUFFLENBQUM7SUFFcEIsMkVBQTJFO0lBQ2pFLFdBQVcsR0FBRyxJQUFJLFlBQVksRUFBZSxDQUFDO0lBQ3hELG9DQUFvQztJQUMxQixNQUFNLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztJQUM1QyxxQ0FBcUM7SUFDM0IsTUFBTSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7SUFFdEIsU0FBUyxDQUEyQjtJQUN0QyxPQUFPLENBQTJCO0lBQ2hDLFVBQVUsQ0FBd0I7SUFFL0MsT0FBTyxHQUFHLHlCQUF5QixHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUV2RixLQUFLLEdBQWdCLElBQUksQ0FBQztJQUMxQixNQUFNLEdBQUcsS0FBSyxDQUFDO0lBRWY7Ozs7T0FJRztJQUNILFdBQVcsQ0FBUTtJQUNuQixXQUFXLENBQVE7SUFFVixpQkFBaUIsR0FBRyxFQUFFLENBQzdCLG9GQUFvRixFQUNwRiw4Q0FBOEMsRUFDOUMseUVBQXlFLENBQzFFLENBQUM7SUFFUSxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBRVYsT0FBTyxDQUFjO0lBQ3JCLFFBQVEsR0FBaUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDO0lBQ2xELFNBQVMsR0FBZSxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUM7SUFFekMsWUFBb0IsR0FBc0I7UUFBdEIsUUFBRyxHQUFILEdBQUcsQ0FBbUI7SUFBRyxDQUFDO0lBRTlDLFdBQVc7UUFDVCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUMvRCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztRQUUvRCxtRUFBbUU7UUFDbkUsdURBQXVEO1FBQ3ZELElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVnQixtQkFBbUIsR0FBRyxDQUFDLEtBQWlCLEVBQUUsRUFBRTtRQUMzRCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBYyxDQUFDO1FBQ3BDLElBQ0UsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLGFBQWEsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDO1lBQy9DLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxFQUM3QyxDQUFDO1lBQ0QsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUMsQ0FBQztJQUVlLGFBQWEsR0FBRyxDQUFDLEtBQW9CLEVBQUUsRUFBRTtRQUN4RCxJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssUUFBUSxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUMxQyxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2IsSUFBSSxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDeEMsQ0FBQztJQUNILENBQUMsQ0FBQztJQUVGLCtDQUErQztJQUUvQyxJQUFJLElBQUk7UUFDTixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNuRCxDQUFDO0lBRUQsSUFBSSxNQUFNO1FBQ1IsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDckQsQ0FBQztJQUVELElBQUksTUFBTTtRQUNSLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ3JELENBQUM7SUFFRCxJQUFJLFlBQVk7UUFDZCxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUs7WUFBRSxPQUFPLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUM7WUFDSCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNoRCxDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsK0VBQStFO1lBQy9FLE1BQU0sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUM3RCxPQUFPLENBQ0wsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDO2dCQUNqQyxHQUFHO2dCQUNILE1BQU07Z0JBQ04sR0FBRztnQkFDSCxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDO2dCQUNoRCxHQUFHO2dCQUNILFFBQVEsQ0FDVCxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFFRDs7O09BR0c7SUFDSCxJQUFJLFVBQVU7UUFDWixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUc7WUFBRSxPQUFPLENBQUMsQ0FBQztRQUN4QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUM7UUFDbkMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQztZQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQ3hDLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUN6RixDQUFDO0lBRUQsSUFBSSxVQUFVO1FBQ1osSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHO1lBQUUsT0FBTyxlQUFlLEdBQUcsQ0FBQyxDQUFDO1FBQzFDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQztRQUNuQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDO1lBQUUsT0FBTyxlQUFlLEdBQUcsQ0FBQyxDQUFDO1FBQzFELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUN6RixDQUFDO0lBRUQsSUFBSSxvQkFBb0I7UUFDdEIsT0FBTyxFQUFFLENBQ1AsNkJBQTZCLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQ3pFLElBQUksQ0FBQyxLQUFLLENBQ1gsQ0FBQztJQUNKLENBQUM7SUFFRCxvREFBb0Q7SUFFcEQsTUFBTTtRQUNKLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzNDLENBQUM7SUFFRCxJQUFJO1FBQ0YsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTztRQUN6QyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztRQUNuQixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ25CLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7UUFFeEIsVUFBVSxDQUFDLEdBQUcsRUFBRTtZQUNkLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN0QixJQUFJLENBQUMsVUFBVSxFQUFFLHNCQUFzQixFQUFFLENBQUM7WUFDMUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDekUsUUFBUSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2pFLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELEtBQUs7UUFDSCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPO1FBQ3pCLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO1FBQ3BCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNoQixJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxLQUFvQjtRQUNuQyxJQUFJLENBQUMsV0FBVyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUMvRSxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFFRCw2Q0FBNkM7SUFFN0M7OztPQUdHO0lBQ0gsWUFBWSxDQUFDLElBQWlCO1FBQzVCLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNWLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNiLE9BQU87UUFDVCxDQUFDO1FBRUQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUM1QixJQUFJLENBQUMsTUFBTSxDQUNULElBQUksSUFBSSxDQUNOLElBQUksQ0FBQyxXQUFXLEVBQUUsRUFDbEIsSUFBSSxDQUFDLFFBQVEsRUFBRSxFQUNmLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFDZCxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUNsQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUNwQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUNwQyxDQUFDLENBQ0YsQ0FDRixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7T0FHRztJQUNILFlBQVksQ0FBQyxLQUFnQjtRQUMzQixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksSUFBSSxFQUFFLENBQUM7UUFDdEMsSUFBSSxDQUFDLE1BQU0sQ0FDVCxJQUFJLElBQUksQ0FDTixJQUFJLENBQUMsV0FBVyxFQUFFLEVBQ2xCLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFDZixJQUFJLENBQUMsT0FBTyxFQUFFLEVBQ2QsS0FBSyxDQUFDLElBQUksRUFDVixLQUFLLENBQUMsTUFBTSxFQUNaLEtBQUssQ0FBQyxNQUFNLEVBQ1osQ0FBQyxDQUNGLENBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRCxLQUFLO1FBQ0gsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsQiwwRUFBMEU7UUFDMUUsMkVBQTJFO1FBQzNFLHNEQUFzRDtRQUN0RCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDZixDQUFDO0lBRUQsSUFBSTtRQUNGLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNiLElBQUksQ0FBQyxTQUFTLEVBQUUsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ3hDLENBQUM7SUFFTyxNQUFNLENBQUMsSUFBaUI7UUFDOUIsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7UUFDbEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNwQixJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM1QixJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFTyxjQUFjO1FBQ3BCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsYUFBYSxDQUFDO1FBQzlDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLEVBQUUsYUFBYSxDQUFDO1FBQzFDLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxLQUFLO1lBQUUsT0FBTztRQUUvQixJQUFJLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRTtZQUM3QyxlQUFlLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRTtnQkFDOUIsUUFBUSxFQUFFLE9BQU87Z0JBQ2pCLFNBQVMsRUFBRSxjQUFjO2dCQUN6QixVQUFVLEVBQUUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLEVBQUUsS0FBSyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7YUFDdkQsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUU7Z0JBQ25CLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRTtvQkFDekIsSUFBSSxFQUFFLENBQUMsR0FBRyxJQUFJO29CQUNkLEdBQUcsRUFBRSxDQUFDLEdBQUcsSUFBSTtvQkFDYixVQUFVLEVBQUUsU0FBUztpQkFDdEIsQ0FBQyxDQUFDO1lBQ0wsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxRQUFRO1FBQ2QsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7UUFDakIsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUM7UUFDekIsUUFBUSxDQUFDLG1CQUFtQixDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDNUUsUUFBUSxDQUFDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3BFLENBQUM7SUFFRCxXQUFXO1FBQ1QsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2xCLENBQUM7SUFFRCw0REFBNEQ7SUFFNUQsVUFBVSxDQUFDLEtBQXVDO1FBQ2hELElBQUksS0FBSyxZQUFZLElBQUksSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUM1QyxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztRQUNyQixDQUFDO2FBQU0sSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxFQUFFLENBQUM7WUFDOUMsTUFBTSxNQUFNLEdBQUcsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDL0IsSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQy9DLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7UUFDcEIsQ0FBQztRQUNELElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVELGdCQUFnQixDQUFDLEVBQWdDO1FBQy9DLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO0lBQ3JCLENBQUM7SUFFRCxpQkFBaUIsQ0FBQyxFQUFjO1FBQzlCLElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxVQUFtQjtRQUNsQyxJQUFJLENBQUMsUUFBUSxHQUFHLFVBQVUsQ0FBQztRQUMzQixJQUFJLFVBQVU7WUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDN0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUMxQixDQUFDO3dHQW5UVSx1QkFBdUI7NEZBQXZCLHVCQUF1QixrYUF0RnZCO1lBQ1Q7Z0JBQ0UsT0FBTyxFQUFFLGlCQUFpQjtnQkFDMUIsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyx1QkFBdUIsQ0FBQztnQkFDdEQsS0FBSyxFQUFFLElBQUk7YUFDWjtTQUNGLGdVQUNTOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZFVCwrRkF0RlMsWUFBWSxrSUFBRSxXQUFXLCtWQUFFLGlCQUFpQiwwT0FBRSxvQkFBb0I7OzRGQXdGakUsdUJBQXVCO2tCQTVGbkMsU0FBUzsrQkFDRSx3QkFBd0IsY0FFdEIsSUFBSSxXQUNQLENBQUMsWUFBWSxFQUFFLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxvQkFBb0IsQ0FBQyxtQkFDNUQsdUJBQXVCLENBQUMsTUFBTSxhQUNwQzt3QkFDVDs0QkFDRSxPQUFPLEVBQUUsaUJBQWlCOzRCQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSx3QkFBd0IsQ0FBQzs0QkFDdEQsS0FBSyxFQUFFLElBQUk7eUJBQ1o7cUJBQ0YsWUFDUzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E2RVQ7c0ZBSVEsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxRQUFRO3NCQUFoQixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBRUcsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLEdBQUc7c0JBQVgsS0FBSztnQkFFRyxHQUFHO3NCQUFYLEtBQUs7Z0JBRUcsYUFBYTtzQkFBckIsS0FBSztnQkFFRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRUcsT0FBTztzQkFBZixLQUFLO2dCQUVHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBRUcsS0FBSztzQkFBYixLQUFLO2dCQUdJLFdBQVc7c0JBQXBCLE1BQU07Z0JBRUcsTUFBTTtzQkFBZixNQUFNO2dCQUVHLE1BQU07c0JBQWYsTUFBTTtnQkFFZSxTQUFTO3NCQUE5QixTQUFTO3VCQUFDLFNBQVM7Z0JBQ0EsT0FBTztzQkFBMUIsU0FBUzt1QkFBQyxPQUFPO2dCQUNJLFVBQVU7c0JBQS9CLFNBQVM7dUJBQUMsU0FBUyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBmb3J3YXJkUmVmLCBFbGVtZW50UmVmLCBWaWV3Q2hpbGQsIENoYW5nZURldGVjdG9yUmVmLCBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiwgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBjb21wdXRlUG9zaXRpb24sIGZsaXAsIHNoaWZ0LCBvZmZzZXQsIGF1dG9VcGRhdGUgfSBmcm9tICdAZmxvYXRpbmctdWkvZG9tJztcbmltcG9ydCB7IGN2YSwgdHlwZSBWYXJpYW50UHJvcHMgfSBmcm9tICdjbGFzcy12YXJpYW5jZS1hdXRob3JpdHknO1xuaW1wb3J0IHsgZm9ybWF0LCBpc1NhbWVEYXksIGlzVmFsaWQsIHN0YXJ0T2ZEYXkgfSBmcm9tICdkYXRlLWZucyc7XG5pbXBvcnQgeyBjbiB9IGZyb20gJy4vdXRpbHMvY24nO1xuaW1wb3J0IHsgQ2FsZW5kYXJDb21wb25lbnQgfSBmcm9tICcuL2NhbGVuZGFyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBUaW1lQ29sdW1uc0NvbXBvbmVudCwgVGltZVBhcnRzLCB0bzEySG91ciB9IGZyb20gJy4vdGltZS1waWNrZXIuY29tcG9uZW50JztcblxuY29uc3QgU0VDT05EU19QRVJfREFZID0gMjQgKiAzNjAwO1xuXG5jb25zdCBkYXRlVGltZVBpY2tlclRyaWdnZXJWYXJpYW50cyA9IGN2YShcbiAgJ2ZsZXggdy1mdWxsIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gZ2FwLTIgcm91bmRlZC1tZCBib3JkZXIgYm9yZGVyLWlucHV0IGJnLWJhY2tncm91bmQgdGV4dC1mb3JlZ3JvdW5kIHNoYWRvdy1zbSB0cmFuc2l0aW9uLWNvbG9ycyAnICtcbiAgICAnZm9jdXM6b3V0bGluZS1ub25lIGZvY3VzLXZpc2libGU6Ym9yZGVyLXByaW1hcnkvODAgZm9jdXMtdmlzaWJsZTpyaW5nLTQgZm9jdXMtdmlzaWJsZTpyaW5nLXJpbmcvMzAgJyArXG4gICAgJ2Rpc2FibGVkOmN1cnNvci1ub3QtYWxsb3dlZCBkaXNhYmxlZDpvcGFjaXR5LTUwJyxcbiAge1xuICAgIHZhcmlhbnRzOiB7XG4gICAgICBzaXplOiB7XG4gICAgICAgIHhzOiAnaC04IHB4LTIgdGV4dC14cycsXG4gICAgICAgIHNtOiAnaC05IHB4LTMgdGV4dC1zbScsXG4gICAgICAgIGRlZmF1bHQ6ICdoLTEwIHB4LTMgdGV4dC1zbScsXG4gICAgICAgIGxnOiAnaC0xMSBweC00IHRleHQtYmFzZScsXG4gICAgICB9LFxuICAgICAgaW52YWxpZDoge1xuICAgICAgICB0cnVlOiAnYm9yZGVyLWRlc3RydWN0aXZlIGZvY3VzLXZpc2libGU6Ym9yZGVyLWRlc3RydWN0aXZlLzgwIGZvY3VzLXZpc2libGU6cmluZy1kZXN0cnVjdGl2ZS8zMCcsXG4gICAgICAgIGZhbHNlOiAnJyxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBkZWZhdWx0VmFyaWFudHM6IHsgc2l6ZTogJ2RlZmF1bHQnLCBpbnZhbGlkOiBmYWxzZSB9LFxuICB9XG4pO1xuXG4vKiogVmFyaWFudCBwcm9wcyBmb3IgdGhlIGRhdGUtdGltZSBwaWNrZXIgdHJpZ2dlci4gKi9cbmV4cG9ydCB0eXBlIERhdGVUaW1lUGlja2VyUHJvcHMgPSBWYXJpYW50UHJvcHM8dHlwZW9mIGRhdGVUaW1lUGlja2VyVHJpZ2dlclZhcmlhbnRzPjtcblxuLyoqXG4gKiBPbmUgY29udHJvbCBmb3IgYSBkYXRlICphbmQqIGEgdGltZTogYHRvbGxlLWNhbGVuZGFyYCBvbiB0aGUgbGVmdCwgdGhlXG4gKiBgdG9sbGUtdGltZS1jb2x1bW5zYCBzdHJpcCBvbiB0aGUgcmlnaHQsIGluIGEgc2luZ2xlIGZsb2F0aW5nIHBhbmVsIHdpdGggYVxuICogQ2xlYXIgLyBEb25lIGZvb3Rlci5cbiAqXG4gKiBUaGUgdmFsdWUgaXMgYSBgRGF0ZWAsIGJlY2F1c2UgYSBkYXRlLXRpbWUgZ2VudWluZWx5IGlzIGEgbW9tZW50LiBDaGFuZ2luZ1xuICogdGhlIGRhdGUgcHJlc2VydmVzIHRoZSBjaG9zZW4gdGltZSBhbmQgY2hhbmdpbmcgdGhlIHRpbWUgcHJlc2VydmVzIHRoZVxuICogY2hvc2VuIGRhdGUg4oCUIHRoZSB0d28gaGFsdmVzIGFyZSBvbmx5IGV2ZXIgcmVjb21iaW5lZCwgbmV2ZXIgcmVzZXQuXG4gKlxuICogSW1wbGVtZW50cyBgQ29udHJvbFZhbHVlQWNjZXNzb3JgLCBzbyBpdCB3b3JrcyB3aXRoIGBuZ01vZGVsYCBhbmQgcmVhY3RpdmVcbiAqIGZvcm1zLiBVc2UgYHRvbGxlLWRhdGUtcGlja2VyYCBmb3IgYSBkYXRlIGFsb25lIGFuZCBgdG9sbGUtdGltZS1waWNrZXJgIGZvciBhXG4gKiB0aW1lIGFsb25lLlxuICogQG5ld1xuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0b2xsZS1kYXRlLXRpbWUtcGlja2VyJyxcbiAgc3R5bGVzOiBbJzpob3N0IHsgZGlzcGxheTogYmxvY2s7IH0nXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRm9ybXNNb2R1bGUsIENhbGVuZGFyQ29tcG9uZW50LCBUaW1lQ29sdW1uc0NvbXBvbmVudF0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IERhdGVUaW1lUGlja2VyQ29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgIH0sXG4gIF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGJ1dHRvblxuICAgICAgI3RyaWdnZXJcbiAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgYXJpYS1oYXNwb3B1cD1cImRpYWxvZ1wiXG4gICAgICBbYXR0ci5hcmlhLWV4cGFuZGVkXT1cImlzT3BlblwiXG4gICAgICBbYXR0ci5hcmlhLWNvbnRyb2xzXT1cImlzT3BlbiA/IHBhbmVsSWQgOiBudWxsXCJcbiAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiYXJpYUxhYmVsIHx8IG51bGxcIlxuICAgICAgW2F0dHIuZGF0YS1zdGF0ZV09XCJpc09wZW4gPyAnb3BlbicgOiAnY2xvc2VkJ1wiXG4gICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgW2NsYXNzXT1cImNvbXB1dGVkVHJpZ2dlckNsYXNzXCJcbiAgICAgIChjbGljayk9XCJ0b2dnbGUoKVwiXG4gICAgICAoa2V5ZG93bik9XCJvblRyaWdnZXJLZXlEb3duKCRldmVudClcIlxuICAgID5cbiAgICAgIDxzcGFuIFtjbGFzc109XCJjbigndHJ1bmNhdGUnLCBkaXNwbGF5VmFsdWUgPyAndGV4dC1mb3JlZ3JvdW5kJyA6ICd0ZXh0LW11dGVkLWZvcmVncm91bmQnKVwiPlxuICAgICAgICB7eyBkaXNwbGF5VmFsdWUgfHwgcGxhY2Vob2xkZXIgfX1cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxpIGNsYXNzPVwicmktY2FsZW5kYXItc2NoZWR1bGUtbGluZSBzaHJpbmstMCB0ZXh0LW11dGVkLWZvcmVncm91bmRcIiBhcmlhLWhpZGRlbj1cInRydWVcIj48L2k+XG4gICAgPC9idXR0b24+XG5cbiAgICA8ZGl2XG4gICAgICAqbmdJZj1cImlzT3BlblwiXG4gICAgICAjcGFuZWxcbiAgICAgIHJvbGU9XCJkaWFsb2dcIlxuICAgICAgW2lkXT1cInBhbmVsSWRcIlxuICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJhcmlhTGFiZWwgfHwgJ0Nob29zZSBhIGRhdGUgYW5kIHRpbWUnXCJcbiAgICAgIGNsYXNzPVwiZml4ZWQgbGVmdC0wIHRvcC0wIHotWzk5OTldXCJcbiAgICAgIHN0eWxlPVwidmlzaWJpbGl0eTogaGlkZGVuXCJcbiAgICA+XG4gICAgICA8ZGl2IGNsYXNzPVwicm91bmRlZC1tZCBib3JkZXIgYm9yZGVyLWJvcmRlciBiZy1wb3BvdmVyIHRleHQtcG9wb3Zlci1mb3JlZ3JvdW5kIHNoYWRvdy1tZFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LWNvbCBzbTpmbGV4LXJvd1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJwLTNcIj5cbiAgICAgICAgICAgIDx0b2xsZS1jYWxlbmRhclxuICAgICAgICAgICAgICBbYm9yZGVyZWRdPVwiZmFsc2VcIlxuICAgICAgICAgICAgICBbc2hvd1F1aWNrQWN0aW9uc109XCJmYWxzZVwiXG4gICAgICAgICAgICAgIFttaW5EYXRlXT1cImNhbGVuZGFyTWluXCJcbiAgICAgICAgICAgICAgW21heERhdGVdPVwiY2FsZW5kYXJNYXhcIlxuICAgICAgICAgICAgICBbbmdNb2RlbF09XCJ2YWx1ZVwiXG4gICAgICAgICAgICAgIChkYXRlU2VsZWN0KT1cIm9uRGF0ZVNlbGVjdCgkZXZlbnQpXCJcbiAgICAgICAgICAgID48L3RvbGxlLWNhbGVuZGFyPlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJvcmRlci10IGJvcmRlci1ib3JkZXIgcC0zIHNtOmJvcmRlci1sIHNtOmJvcmRlci10LTBcIj5cbiAgICAgICAgICAgIDx0b2xsZS10aW1lLWNvbHVtbnNcbiAgICAgICAgICAgICAgI2NvbHVtbnNcbiAgICAgICAgICAgICAgW2hvdXJdPVwiaG91clwiXG4gICAgICAgICAgICAgIFttaW51dGVdPVwibWludXRlXCJcbiAgICAgICAgICAgICAgW3NlY29uZF09XCJzZWNvbmRcIlxuICAgICAgICAgICAgICBbdXNlMTJIb3Vyc109XCJ1c2UxMkhvdXJzXCJcbiAgICAgICAgICAgICAgW3Nob3dTZWNvbmRzXT1cInNob3dTZWNvbmRzXCJcbiAgICAgICAgICAgICAgW21pbnV0ZVN0ZXBdPVwibWludXRlU3RlcFwiXG4gICAgICAgICAgICAgIFttaW5TZWNvbmRzXT1cIm1pblNlY29uZHNcIlxuICAgICAgICAgICAgICBbbWF4U2Vjb25kc109XCJtYXhTZWNvbmRzXCJcbiAgICAgICAgICAgICAgW3NpemVdPVwic2l6ZVwiXG4gICAgICAgICAgICAgICh0aW1lQ2hhbmdlKT1cIm9uVGltZUNoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgICAgID48L3RvbGxlLXRpbWUtY29sdW1ucz5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktYmV0d2VlbiBnYXAtMiBib3JkZXItdCBib3JkZXItYm9yZGVyIHB4LTMgcHktMlwiPlxuICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgW2NsYXNzXT1cImZvb3RlckJ1dHRvbkNsYXNzXCJcbiAgICAgICAgICAgIChjbGljayk9XCJjbGVhcigpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICBDbGVhclxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgW2NsYXNzXT1cImNuKGZvb3RlckJ1dHRvbkNsYXNzLCAnYmctcHJpbWFyeSB0ZXh0LXByaW1hcnktZm9yZWdyb3VuZCBob3ZlcjpiZy1wcmltYXJ5LzkwIGhvdmVyOnRleHQtcHJpbWFyeS1mb3JlZ3JvdW5kJylcIlxuICAgICAgICAgICAgKGNsaWNrKT1cImRvbmUoKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgRG9uZVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBEYXRlVGltZVBpY2tlckNvbXBvbmVudCBpbXBsZW1lbnRzIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XG4gIC8qKiBUZXh0IHNob3duIG9uIHRoZSB0cmlnZ2VyIHdoZW4gbm90aGluZyBpcyBzZWxlY3RlZC4gQGRlZmF1bHQgJ1NlbGVjdCBkYXRlIGFuZCB0aW1lJyAqL1xuICBASW5wdXQoKSBwbGFjZWhvbGRlciA9ICdTZWxlY3QgZGF0ZSBhbmQgdGltZSc7XG4gIC8qKiBEaXNhYmxlcyB0aGUgY29udHJvbC4gQGRlZmF1bHQgZmFsc2UgKi9cbiAgQElucHV0KCkgZGlzYWJsZWQgPSBmYWxzZTtcbiAgLyoqIFJlbmRlcnMgYSAxMi1ob3VyIGZhY2Ugd2l0aCBhbiBBTS9QTSBjb2x1bW4uIEBkZWZhdWx0IGZhbHNlICovXG4gIEBJbnB1dCgpIHVzZTEySG91cnMgPSBmYWxzZTtcbiAgLyoqIEFkZHMgYSBzZWNvbmRzIGNvbHVtbi4gQGRlZmF1bHQgZmFsc2UgKi9cbiAgQElucHV0KCkgc2hvd1NlY29uZHMgPSBmYWxzZTtcbiAgLyoqIEludGVydmFsIGJldHdlZW4gbWludXRlIGVudHJpZXMsIGluIG1pbnV0ZXMuIEBkZWZhdWx0IDEgKi9cbiAgQElucHV0KCkgbWludXRlU3RlcCA9IDE7XG4gIC8qKiBFYXJsaWVzdCBzZWxlY3RhYmxlIG1vbWVudDsgZWFybGllciBkYXlzIGFuZCB0aW1lcyBhcmUgZGlzYWJsZWQuICovXG4gIEBJbnB1dCgpIG1pbj86IERhdGU7XG4gIC8qKiBMYXRlc3Qgc2VsZWN0YWJsZSBtb21lbnQ7IGxhdGVyIGRheXMgYW5kIHRpbWVzIGFyZSBkaXNhYmxlZC4gKi9cbiAgQElucHV0KCkgbWF4PzogRGF0ZTtcbiAgLyoqIGRhdGUtZm5zIHBhdHRlcm4gdXNlZCB0byByZW5kZXIgdGhlIHZhbHVlIG9uIHRoZSB0cmlnZ2VyLiBAZGVmYXVsdCAnTU1NIGQsIHl5eXkgaDptbSBhJyAqL1xuICBASW5wdXQoKSBkaXNwbGF5Rm9ybWF0ID0gJ01NTSBkLCB5eXl5IGg6bW0gYSc7XG4gIC8qKiBIZWlnaHQgYW5kIHRleHQgc2l6ZSBvZiB0aGUgdHJpZ2dlciBhbmQgZW50cmllcy4gQGRlZmF1bHQgJ2RlZmF1bHQnICovXG4gIEBJbnB1dCgpIHNpemU6IERhdGVUaW1lUGlja2VyUHJvcHNbJ3NpemUnXSA9ICdkZWZhdWx0JztcbiAgLyoqIEFwcGxpZXMgdGhlIGRlc3RydWN0aXZlIGJvcmRlciBhbmQgZm9jdXMgcmluZy4gQGRlZmF1bHQgZmFsc2UgKi9cbiAgQElucHV0KCkgaW52YWxpZCA9IGZhbHNlO1xuICAvKiogQWNjZXNzaWJsZSBuYW1lIHdoZW4gdGhlcmUgaXMgbm8gYXNzb2NpYXRlZCB2aXNpYmxlIGxhYmVsLiBAZGVmYXVsdCAnJyAqL1xuICBASW5wdXQoKSBhcmlhTGFiZWwgPSAnJztcbiAgLyoqIEV4dHJhIFRhaWx3aW5kIGNsYXNzZXMgbWVyZ2VkIG9udG8gdGhlIHRyaWdnZXIgdmlhIGBjbigpYCAobGFzdC13aW5zKS4gKi9cbiAgQElucHV0KCkgY2xhc3MgPSAnJztcblxuICAvKiogRW1pdHRlZCB3aXRoIHRoZSBjaG9zZW4gbW9tZW50LCBvciBgbnVsbGAgd2hlbiB0aGUgdmFsdWUgaXMgY2xlYXJlZC4gKi9cbiAgQE91dHB1dCgpIHZhbHVlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRlIHwgbnVsbD4oKTtcbiAgLyoqIEVtaXR0ZWQgd2hlbiB0aGUgcGFuZWwgb3BlbnMuICovXG4gIEBPdXRwdXQoKSBvcGVuZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG4gIC8qKiBFbWl0dGVkIHdoZW4gdGhlIHBhbmVsIGNsb3Nlcy4gKi9cbiAgQE91dHB1dCgpIGNsb3NlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICBAVmlld0NoaWxkKCd0cmlnZ2VyJykgdHJpZ2dlckVsPzogRWxlbWVudFJlZjxIVE1MRWxlbWVudD47XG4gIEBWaWV3Q2hpbGQoJ3BhbmVsJykgcGFuZWxFbD86IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+O1xuICBAVmlld0NoaWxkKCdjb2x1bW5zJykgY29sdW1uc0NtcD86IFRpbWVDb2x1bW5zQ29tcG9uZW50O1xuXG4gIHJlYWRvbmx5IHBhbmVsSWQgPSAnZGF0ZS10aW1lLXBpY2tlci1wYW5lbC0nICsgTWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc2xpY2UoMiwgMTEpO1xuXG4gIHZhbHVlOiBEYXRlIHwgbnVsbCA9IG51bGw7XG4gIGlzT3BlbiA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBEYXktb25seSBjb3BpZXMgb2YgYG1pbmAgLyBgbWF4YCBmb3IgdGhlIGNhbGVuZGFyLiBUaGUgY2FsZW5kYXIgY29tcGFyZXNcbiAgICogd2hvbGUgYERhdGVgcywgc28gcGFzc2luZyBhIGJvdW5kIHRoYXQgY2FycmllcyBhIHRpbWUgd291bGQgZGlzYWJsZSBpdHMgb3duXG4gICAqIGRheSDigJQgMDk6MDAgb24gdGhlIG1pbiBkYXkgd291bGQgbG9vayBcImJlZm9yZVwiIGEgMDk6MzAgbWluaW11bS5cbiAgICovXG4gIGNhbGVuZGFyTWluPzogRGF0ZTtcbiAgY2FsZW5kYXJNYXg/OiBEYXRlO1xuXG4gIHJlYWRvbmx5IGZvb3RlckJ1dHRvbkNsYXNzID0gY24oXG4gICAgJ3JvdW5kZWQtbWQgcHgtMyBweS0xLjUgdGV4dC1zbSBmb250LW1lZGl1bSB0ZXh0LW11dGVkLWZvcmVncm91bmQgdHJhbnNpdGlvbi1jb2xvcnMnLFxuICAgICdob3ZlcjpiZy1hY2NlbnQgaG92ZXI6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCcsXG4gICAgJ2ZvY3VzLXZpc2libGU6b3V0bGluZS1ub25lIGZvY3VzLXZpc2libGU6cmluZy0yIGZvY3VzLXZpc2libGU6cmluZy1yaW5nJ1xuICApO1xuXG4gIHByb3RlY3RlZCBjbiA9IGNuO1xuXG4gIHByaXZhdGUgY2xlYW51cD86ICgpID0+IHZvaWQ7XG4gIHByaXZhdGUgb25DaGFuZ2U6ICh2YWx1ZTogRGF0ZSB8IG51bGwpID0+IHZvaWQgPSAoKSA9PiB7fTtcbiAgcHJpdmF0ZSBvblRvdWNoZWQ6ICgpID0+IHZvaWQgPSAoKSA9PiB7fTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGNkcjogQ2hhbmdlRGV0ZWN0b3JSZWYpIHt9XG5cbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5jYWxlbmRhck1pbiA9IHRoaXMubWluID8gc3RhcnRPZkRheSh0aGlzLm1pbikgOiB1bmRlZmluZWQ7XG4gICAgdGhpcy5jYWxlbmRhck1heCA9IHRoaXMubWF4ID8gc3RhcnRPZkRheSh0aGlzLm1heCkgOiB1bmRlZmluZWQ7XG4gIFxuICAgIC8vIEEgYm91bmQgYGNsYXNzYCBpbnB1dCBpcyB3cml0dGVuIHRocm91Z2ggQW5ndWxhcidzIHN0eWxpbmcgcGF0aCxcbiAgICAvLyB3aGljaCBkb2VzIG5vdCBtYXJrIGFuIE9uUHVzaCB2aWV3IGRpcnR5IG9uIGl0cyBvd24uXG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IG91dHNpZGVDbGlja0hhbmRsZXIgPSAoZXZlbnQ6IE1vdXNlRXZlbnQpID0+IHtcbiAgICBjb25zdCB0YXJnZXQgPSBldmVudC50YXJnZXQgYXMgTm9kZTtcbiAgICBpZiAoXG4gICAgICAhdGhpcy50cmlnZ2VyRWw/Lm5hdGl2ZUVsZW1lbnQuY29udGFpbnModGFyZ2V0KSAmJlxuICAgICAgIXRoaXMucGFuZWxFbD8ubmF0aXZlRWxlbWVudC5jb250YWlucyh0YXJnZXQpXG4gICAgKSB7XG4gICAgICB0aGlzLmNsb3NlKCk7XG4gICAgfVxuICB9O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgZXNjYXBlSGFuZGxlciA9IChldmVudDogS2V5Ym9hcmRFdmVudCkgPT4ge1xuICAgIGlmIChldmVudC5rZXkgPT09ICdFc2NhcGUnICYmIHRoaXMuaXNPcGVuKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgdGhpcy5jbG9zZSgpO1xuICAgICAgdGhpcy50cmlnZ2VyRWw/Lm5hdGl2ZUVsZW1lbnQuZm9jdXMoKTtcbiAgICB9XG4gIH07XG5cbiAgLyogLS0tLS0tLS0tLS0tLS0tLSBkZXJpdmVkIC0tLS0tLS0tLS0tLS0tLS0gKi9cblxuICBnZXQgaG91cigpOiBudW1iZXIgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZSA/IHRoaXMudmFsdWUuZ2V0SG91cnMoKSA6IG51bGw7XG4gIH1cblxuICBnZXQgbWludXRlKCk6IG51bWJlciB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLnZhbHVlID8gdGhpcy52YWx1ZS5nZXRNaW51dGVzKCkgOiBudWxsO1xuICB9XG5cbiAgZ2V0IHNlY29uZCgpOiBudW1iZXIgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZSA/IHRoaXMudmFsdWUuZ2V0U2Vjb25kcygpIDogbnVsbDtcbiAgfVxuXG4gIGdldCBkaXNwbGF5VmFsdWUoKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMudmFsdWUpIHJldHVybiAnJztcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGZvcm1hdCh0aGlzLnZhbHVlLCB0aGlzLmRpc3BsYXlGb3JtYXQpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gQSBiYWQgcGF0dGVybiBzaG91bGQgbm90IGJsYW5rIHRoZSBjb250cm9sOyBmYWxsIGJhY2sgdG8gc29tZXRoaW5nIHJlYWRhYmxlLlxuICAgICAgY29uc3QgeyBob3VyMTIsIG1lcmlkaWVtIH0gPSB0bzEySG91cih0aGlzLnZhbHVlLmdldEhvdXJzKCkpO1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgZm9ybWF0KHRoaXMudmFsdWUsICdNTU0gZCwgeXl5eScpICtcbiAgICAgICAgJyAnICtcbiAgICAgICAgaG91cjEyICtcbiAgICAgICAgJzonICtcbiAgICAgICAgU3RyaW5nKHRoaXMudmFsdWUuZ2V0TWludXRlcygpKS5wYWRTdGFydCgyLCAnMCcpICtcbiAgICAgICAgJyAnICtcbiAgICAgICAgbWVyaWRpZW1cbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRoZSB0aW1lIGJvdW5kIG9ubHkgYml0ZXMgb24gdGhlIGJvdW5kYXJ5IGRheSBpdHNlbGY6IG9uIHRoZSBtaW4gZGF5IHRoZVxuICAgKiBjb2x1bW5zIHN0YXJ0IGF0IHRoZSBtaW4gdGltZSwgb24gYW55IGxhdGVyIGRheSB0aGV5IHN0YXJ0IGF0IG1pZG5pZ2h0LlxuICAgKi9cbiAgZ2V0IG1pblNlY29uZHMoKTogbnVtYmVyIHtcbiAgICBpZiAoIXRoaXMubWluKSByZXR1cm4gMDtcbiAgICBjb25zdCBkYXkgPSB0aGlzLnZhbHVlID8/IHRoaXMubWluO1xuICAgIGlmICghaXNTYW1lRGF5KGRheSwgdGhpcy5taW4pKSByZXR1cm4gMDtcbiAgICByZXR1cm4gdGhpcy5taW4uZ2V0SG91cnMoKSAqIDM2MDAgKyB0aGlzLm1pbi5nZXRNaW51dGVzKCkgKiA2MCArIHRoaXMubWluLmdldFNlY29uZHMoKTtcbiAgfVxuXG4gIGdldCBtYXhTZWNvbmRzKCk6IG51bWJlciB7XG4gICAgaWYgKCF0aGlzLm1heCkgcmV0dXJuIFNFQ09ORFNfUEVSX0RBWSAtIDE7XG4gICAgY29uc3QgZGF5ID0gdGhpcy52YWx1ZSA/PyB0aGlzLm1heDtcbiAgICBpZiAoIWlzU2FtZURheShkYXksIHRoaXMubWF4KSkgcmV0dXJuIFNFQ09ORFNfUEVSX0RBWSAtIDE7XG4gICAgcmV0dXJuIHRoaXMubWF4LmdldEhvdXJzKCkgKiAzNjAwICsgdGhpcy5tYXguZ2V0TWludXRlcygpICogNjAgKyB0aGlzLm1heC5nZXRTZWNvbmRzKCk7XG4gIH1cblxuICBnZXQgY29tcHV0ZWRUcmlnZ2VyQ2xhc3MoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gY24oXG4gICAgICBkYXRlVGltZVBpY2tlclRyaWdnZXJWYXJpYW50cyh7IHNpemU6IHRoaXMuc2l6ZSwgaW52YWxpZDogdGhpcy5pbnZhbGlkIH0pLFxuICAgICAgdGhpcy5jbGFzc1xuICAgICk7XG4gIH1cblxuICAvKiAtLS0tLS0tLS0tLS0tLS0tIG9wZW4gLyBjbG9zZSAtLS0tLS0tLS0tLS0tLS0tICovXG5cbiAgdG9nZ2xlKCk6IHZvaWQge1xuICAgIHRoaXMuaXNPcGVuID8gdGhpcy5jbG9zZSgpIDogdGhpcy5vcGVuKCk7XG4gIH1cblxuICBvcGVuKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc2FibGVkIHx8IHRoaXMuaXNPcGVuKSByZXR1cm47XG4gICAgdGhpcy5pc09wZW4gPSB0cnVlO1xuICAgIHRoaXMub3BlbmVkLmVtaXQoKTtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy51cGRhdGVQb3NpdGlvbigpO1xuICAgICAgdGhpcy5jb2x1bW5zQ21wPy5zY3JvbGxTZWxlY3RlZEludG9WaWV3KCk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdwb2ludGVyZG93bicsIHRoaXMub3V0c2lkZUNsaWNrSGFuZGxlciwgdHJ1ZSk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5lc2NhcGVIYW5kbGVyLCB0cnVlKTtcbiAgICB9KTtcbiAgfVxuXG4gIGNsb3NlKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5pc09wZW4pIHJldHVybjtcbiAgICB0aGlzLmlzT3BlbiA9IGZhbHNlO1xuICAgIHRoaXMuY2xvc2VkLmVtaXQoKTtcbiAgICB0aGlzLm9uVG91Y2hlZCgpO1xuICAgIHRoaXMudGVhcmRvd24oKTtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIG9uVHJpZ2dlcktleURvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoWydBcnJvd0Rvd24nLCAnQXJyb3dVcCcsICdFbnRlcicsICcgJ10uaW5jbHVkZXMoZXZlbnQua2V5KSAmJiAhdGhpcy5pc09wZW4pIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB0aGlzLm9wZW4oKTtcbiAgICB9XG4gIH1cblxuICAvKiAtLS0tLS0tLS0tLS0tLS0tIHZhbHVlIC0tLS0tLS0tLS0tLS0tLS0gKi9cblxuICAvKipcbiAgICogQXBwbGllcyBhIG5ld2x5IHBpY2tlZCBkYXksIGNhcnJ5aW5nIHRoZSBleGlzdGluZyB0aW1lIGFjcm9zcy4gV2l0aCBub1xuICAgKiB0aW1lIGNob3NlbiB5ZXQgdGhlIGRheSBzdGFydHMgYXQgbWlkbmlnaHQuXG4gICAqL1xuICBvbkRhdGVTZWxlY3QoZGF0ZTogRGF0ZSB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAoIWRhdGUpIHtcbiAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwcmV2aW91cyA9IHRoaXMudmFsdWU7XG4gICAgdGhpcy5jb21taXQoXG4gICAgICBuZXcgRGF0ZShcbiAgICAgICAgZGF0ZS5nZXRGdWxsWWVhcigpLFxuICAgICAgICBkYXRlLmdldE1vbnRoKCksXG4gICAgICAgIGRhdGUuZ2V0RGF0ZSgpLFxuICAgICAgICBwcmV2aW91cyA/IHByZXZpb3VzLmdldEhvdXJzKCkgOiAwLFxuICAgICAgICBwcmV2aW91cyA/IHByZXZpb3VzLmdldE1pbnV0ZXMoKSA6IDAsXG4gICAgICAgIHByZXZpb3VzID8gcHJldmlvdXMuZ2V0U2Vjb25kcygpIDogMCxcbiAgICAgICAgMFxuICAgICAgKVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQXBwbGllcyBhIG5ld2x5IHBpY2tlZCB0aW1lLCBjYXJyeWluZyB0aGUgZXhpc3RpbmcgZGF5IGFjcm9zcy4gV2l0aCBubyBkYXlcbiAgICogY2hvc2VuIHlldCB0aGUgdGltZSBsYW5kcyBvbiB0b2RheS5cbiAgICovXG4gIG9uVGltZUNoYW5nZShwYXJ0czogVGltZVBhcnRzKTogdm9pZCB7XG4gICAgY29uc3QgYmFzZSA9IHRoaXMudmFsdWUgPz8gbmV3IERhdGUoKTtcbiAgICB0aGlzLmNvbW1pdChcbiAgICAgIG5ldyBEYXRlKFxuICAgICAgICBiYXNlLmdldEZ1bGxZZWFyKCksXG4gICAgICAgIGJhc2UuZ2V0TW9udGgoKSxcbiAgICAgICAgYmFzZS5nZXREYXRlKCksXG4gICAgICAgIHBhcnRzLmhvdXIsXG4gICAgICAgIHBhcnRzLm1pbnV0ZSxcbiAgICAgICAgcGFydHMuc2Vjb25kLFxuICAgICAgICAwXG4gICAgICApXG4gICAgKTtcbiAgfVxuXG4gIGNsZWFyKCk6IHZvaWQge1xuICAgIHRoaXMuY29tbWl0KG51bGwpO1xuICAgIC8vIFRoZSBjYWxlbmRhciBrZWVwcyBpdHMgb3duIHNlbGVjdGlvbiBhbmQgaWdub3JlcyBhIG51bGwgd3JpdHRlbiB0aHJvdWdoXG4gICAgLy8gdGhlIENWQSwgc28gY2xvc2luZyBpcyB3aGF0IGFjdHVhbGx5IHJldHVybnMgaXQgdG8gYSBjbGVhbiBzdGF0ZSDigJQgaXQgaXNcbiAgICAvLyByZWJ1aWx0IGZyb20gc2NyYXRjaCB0aGUgbmV4dCB0aW1lIHRoZSBwYW5lbCBvcGVucy5cbiAgICB0aGlzLmNsb3NlKCk7XG4gIH1cblxuICBkb25lKCk6IHZvaWQge1xuICAgIHRoaXMuY2xvc2UoKTtcbiAgICB0aGlzLnRyaWdnZXJFbD8ubmF0aXZlRWxlbWVudC5mb2N1cygpO1xuICB9XG5cbiAgcHJpdmF0ZSBjb21taXQobmV4dDogRGF0ZSB8IG51bGwpOiB2b2lkIHtcbiAgICB0aGlzLnZhbHVlID0gbmV4dDtcbiAgICB0aGlzLm9uQ2hhbmdlKG5leHQpO1xuICAgIHRoaXMudmFsdWVDaGFuZ2UuZW1pdChuZXh0KTtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlUG9zaXRpb24oKTogdm9pZCB7XG4gICAgY29uc3QgdHJpZ2dlciA9IHRoaXMudHJpZ2dlckVsPy5uYXRpdmVFbGVtZW50O1xuICAgIGNvbnN0IHBhbmVsID0gdGhpcy5wYW5lbEVsPy5uYXRpdmVFbGVtZW50O1xuICAgIGlmICghdHJpZ2dlciB8fCAhcGFuZWwpIHJldHVybjtcblxuICAgIHRoaXMuY2xlYW51cCA9IGF1dG9VcGRhdGUodHJpZ2dlciwgcGFuZWwsICgpID0+IHtcbiAgICAgIGNvbXB1dGVQb3NpdGlvbih0cmlnZ2VyLCBwYW5lbCwge1xuICAgICAgICBzdHJhdGVneTogJ2ZpeGVkJyxcbiAgICAgICAgcGxhY2VtZW50OiAnYm90dG9tLXN0YXJ0JyxcbiAgICAgICAgbWlkZGxld2FyZTogW29mZnNldCg0KSwgZmxpcCgpLCBzaGlmdCh7IHBhZGRpbmc6IDggfSldLFxuICAgICAgfSkudGhlbigoeyB4LCB5IH0pID0+IHtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihwYW5lbC5zdHlsZSwge1xuICAgICAgICAgIGxlZnQ6IHggKyAncHgnLFxuICAgICAgICAgIHRvcDogeSArICdweCcsXG4gICAgICAgICAgdmlzaWJpbGl0eTogJ3Zpc2libGUnLFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSB0ZWFyZG93bigpOiB2b2lkIHtcbiAgICB0aGlzLmNsZWFudXA/LigpO1xuICAgIHRoaXMuY2xlYW51cCA9IHVuZGVmaW5lZDtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdwb2ludGVyZG93bicsIHRoaXMub3V0c2lkZUNsaWNrSGFuZGxlciwgdHJ1ZSk7XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuZXNjYXBlSGFuZGxlciwgdHJ1ZSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnRlYXJkb3duKCk7XG4gIH1cblxuICAvKiAtLS0tLS0tLS0tLS0tLS0tIENvbnRyb2xWYWx1ZUFjY2Vzc29yIC0tLS0tLS0tLS0tLS0tLS0gKi9cblxuICB3cml0ZVZhbHVlKHZhbHVlOiBEYXRlIHwgc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHZvaWQge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERhdGUgJiYgaXNWYWxpZCh2YWx1ZSkpIHtcbiAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUpIHtcbiAgICAgIGNvbnN0IHBhcnNlZCA9IG5ldyBEYXRlKHZhbHVlKTtcbiAgICAgIHRoaXMudmFsdWUgPSBpc1ZhbGlkKHBhcnNlZCkgPyBwYXJzZWQgOiBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnZhbHVlID0gbnVsbDtcbiAgICB9XG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICByZWdpc3Rlck9uQ2hhbmdlKGZuOiAodmFsdWU6IERhdGUgfCBudWxsKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5vbkNoYW5nZSA9IGZuO1xuICB9XG5cbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICB9XG5cbiAgc2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG4gICAgaWYgKGlzRGlzYWJsZWQpIHRoaXMuY2xvc2UoKTtcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Directive, Injectable, Input, Output, EventEmitter, HostBinding, inject, } from '@angular/core';
|
|
2
|
+
import { BehaviorSubject } from 'rxjs';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
/**
|
|
5
|
+
* Publishes the application's current writing direction so components can adapt
|
|
6
|
+
* without reading the DOM.
|
|
7
|
+
*
|
|
8
|
+
* Direction is not an input of most components, so an OnPush view would never be
|
|
9
|
+
* marked dirty by a change. Subscribe to `direction$` and call `markForCheck()`
|
|
10
|
+
* on emission wherever the rendered output depends on it.
|
|
11
|
+
*/
|
|
12
|
+
export class DirectionService {
|
|
13
|
+
directionSource = new BehaviorSubject('ltr');
|
|
14
|
+
/** Emits the current writing direction, starting with the present value. */
|
|
15
|
+
direction$ = this.directionSource.asObservable();
|
|
16
|
+
/** The current writing direction. */
|
|
17
|
+
get direction() {
|
|
18
|
+
return this.directionSource.value;
|
|
19
|
+
}
|
|
20
|
+
/** Whether the current direction is explicitly right-to-left. */
|
|
21
|
+
get isRtl() {
|
|
22
|
+
return this.directionSource.value === 'rtl';
|
|
23
|
+
}
|
|
24
|
+
/** Sets the current direction, emitting only when it actually changes. */
|
|
25
|
+
setDirection(direction) {
|
|
26
|
+
if (this.directionSource.value !== direction)
|
|
27
|
+
this.directionSource.next(direction);
|
|
28
|
+
}
|
|
29
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DirectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
30
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DirectionService, providedIn: 'root' });
|
|
31
|
+
}
|
|
32
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DirectionService, decorators: [{
|
|
33
|
+
type: Injectable,
|
|
34
|
+
args: [{ providedIn: 'root' }]
|
|
35
|
+
}] });
|
|
36
|
+
/**
|
|
37
|
+
* Sets the `dir` attribute on its host and publishes that direction to
|
|
38
|
+
* `DirectionService`, so a whole chat surface can be flipped to RTL from one
|
|
39
|
+
* place. Put it on the outermost element of the subtree you want to flip.
|
|
40
|
+
* @new
|
|
41
|
+
*/
|
|
42
|
+
export class DirectionDirective {
|
|
43
|
+
/** Writing direction applied to the host's `dir` attribute. @default 'ltr' */
|
|
44
|
+
tolleDirection = 'ltr';
|
|
45
|
+
/** Whether to publish this direction to the app-wide `DirectionService`. @default true */
|
|
46
|
+
tolleDirectionPublish = true;
|
|
47
|
+
/** Emitted with the direction whenever it changes. */
|
|
48
|
+
directionChange = new EventEmitter();
|
|
49
|
+
service = inject(DirectionService);
|
|
50
|
+
/** The resolved `dir` attribute value written onto the host. */
|
|
51
|
+
get dir() {
|
|
52
|
+
return this.tolleDirection ?? 'ltr';
|
|
53
|
+
}
|
|
54
|
+
ngOnChanges() {
|
|
55
|
+
const direction = this.dir;
|
|
56
|
+
if (this.tolleDirectionPublish)
|
|
57
|
+
this.service.setDirection(direction);
|
|
58
|
+
this.directionChange.emit(direction);
|
|
59
|
+
}
|
|
60
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DirectionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
61
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.14", type: DirectionDirective, isStandalone: true, selector: "[tolleDirection]", inputs: { tolleDirection: "tolleDirection", tolleDirectionPublish: "tolleDirectionPublish" }, outputs: { directionChange: "directionChange" }, host: { properties: { "attr.dir": "this.dir" } }, usesOnChanges: true, ngImport: i0 });
|
|
62
|
+
}
|
|
63
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DirectionDirective, decorators: [{
|
|
64
|
+
type: Directive,
|
|
65
|
+
args: [{
|
|
66
|
+
selector: '[tolleDirection]',
|
|
67
|
+
standalone: true,
|
|
68
|
+
}]
|
|
69
|
+
}], propDecorators: { tolleDirection: [{
|
|
70
|
+
type: Input
|
|
71
|
+
}], tolleDirectionPublish: [{
|
|
72
|
+
type: Input
|
|
73
|
+
}], directionChange: [{
|
|
74
|
+
type: Output
|
|
75
|
+
}], dir: [{
|
|
76
|
+
type: HostBinding,
|
|
77
|
+
args: ['attr.dir']
|
|
78
|
+
}] } });
|
|
79
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlyZWN0aW9uLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL3RvbGxlL3NyYy9saWIvZGlyZWN0aW9uLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULFVBQVUsRUFDVixLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksRUFDWixXQUFXLEVBRVgsTUFBTSxHQUNQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUM7O0FBS3ZDOzs7Ozs7O0dBT0c7QUFFSCxNQUFNLE9BQU8sZ0JBQWdCO0lBQ25CLGVBQWUsR0FBRyxJQUFJLGVBQWUsQ0FBWSxLQUFLLENBQUMsQ0FBQztJQUVoRSw0RUFBNEU7SUFDbkUsVUFBVSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsWUFBWSxFQUFFLENBQUM7SUFFMUQscUNBQXFDO0lBQ3JDLElBQUksU0FBUztRQUNYLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUM7SUFDcEMsQ0FBQztJQUVELGlFQUFpRTtJQUNqRSxJQUFJLEtBQUs7UUFDUCxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxLQUFLLEtBQUssQ0FBQztJQUM5QyxDQUFDO0lBRUQsMEVBQTBFO0lBQzFFLFlBQVksQ0FBQyxTQUFvQjtRQUMvQixJQUFJLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxLQUFLLFNBQVM7WUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNyRixDQUFDO3dHQW5CVSxnQkFBZ0I7NEdBQWhCLGdCQUFnQixjQURILE1BQU07OzRGQUNuQixnQkFBZ0I7a0JBRDVCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFOztBQXVCbEM7Ozs7O0dBS0c7QUFLSCxNQUFNLE9BQU8sa0JBQWtCO0lBQzdCLDhFQUE4RTtJQUNyRSxjQUFjLEdBQWMsS0FBSyxDQUFDO0lBQzNDLDBGQUEwRjtJQUNqRixxQkFBcUIsR0FBRyxJQUFJLENBQUM7SUFFdEMsc0RBQXNEO0lBQzVDLGVBQWUsR0FBRyxJQUFJLFlBQVksRUFBYSxDQUFDO0lBRXpDLE9BQU8sR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUVwRCxnRUFBZ0U7SUFDaEUsSUFDSSxHQUFHO1FBQ0wsT0FBTyxJQUFJLENBQUMsY0FBYyxJQUFJLEtBQUssQ0FBQztJQUN0QyxDQUFDO0lBRUQsV0FBVztRQUNULE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUM7UUFDM0IsSUFBSSxJQUFJLENBQUMscUJBQXFCO1lBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDdkMsQ0FBQzt3R0FyQlUsa0JBQWtCOzRGQUFsQixrQkFBa0I7OzRGQUFsQixrQkFBa0I7a0JBSjlCLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLGtCQUFrQjtvQkFDNUIsVUFBVSxFQUFFLElBQUk7aUJBQ2pCOzhCQUdVLGNBQWM7c0JBQXRCLEtBQUs7Z0JBRUcscUJBQXFCO3NCQUE3QixLQUFLO2dCQUdJLGVBQWU7c0JBQXhCLE1BQU07Z0JBTUgsR0FBRztzQkFETixXQUFXO3VCQUFDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBEaXJlY3RpdmUsXG4gIEluamVjdGFibGUsXG4gIElucHV0LFxuICBPdXRwdXQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdEJpbmRpbmcsXG4gIE9uQ2hhbmdlcyxcbiAgaW5qZWN0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuXG4vKiogV3JpdGluZyBkaXJlY3Rpb24gb2YgYSBzdWJ0cmVlOiBleHBsaWNpdCwgb3IgaW5mZXJyZWQgZnJvbSBpdHMgdGV4dC4gKi9cbmV4cG9ydCB0eXBlIERpcmVjdGlvbiA9ICdsdHInIHwgJ3J0bCcgfCAnYXV0byc7XG5cbi8qKlxuICogUHVibGlzaGVzIHRoZSBhcHBsaWNhdGlvbidzIGN1cnJlbnQgd3JpdGluZyBkaXJlY3Rpb24gc28gY29tcG9uZW50cyBjYW4gYWRhcHRcbiAqIHdpdGhvdXQgcmVhZGluZyB0aGUgRE9NLlxuICpcbiAqIERpcmVjdGlvbiBpcyBub3QgYW4gaW5wdXQgb2YgbW9zdCBjb21wb25lbnRzLCBzbyBhbiBPblB1c2ggdmlldyB3b3VsZCBuZXZlciBiZVxuICogbWFya2VkIGRpcnR5IGJ5IGEgY2hhbmdlLiBTdWJzY3JpYmUgdG8gYGRpcmVjdGlvbiRgIGFuZCBjYWxsIGBtYXJrRm9yQ2hlY2soKWBcbiAqIG9uIGVtaXNzaW9uIHdoZXJldmVyIHRoZSByZW5kZXJlZCBvdXRwdXQgZGVwZW5kcyBvbiBpdC5cbiAqL1xuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBEaXJlY3Rpb25TZXJ2aWNlIHtcbiAgcHJpdmF0ZSBkaXJlY3Rpb25Tb3VyY2UgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PERpcmVjdGlvbj4oJ2x0cicpO1xuXG4gIC8qKiBFbWl0cyB0aGUgY3VycmVudCB3cml0aW5nIGRpcmVjdGlvbiwgc3RhcnRpbmcgd2l0aCB0aGUgcHJlc2VudCB2YWx1ZS4gKi9cbiAgcmVhZG9ubHkgZGlyZWN0aW9uJCA9IHRoaXMuZGlyZWN0aW9uU291cmNlLmFzT2JzZXJ2YWJsZSgpO1xuXG4gIC8qKiBUaGUgY3VycmVudCB3cml0aW5nIGRpcmVjdGlvbi4gKi9cbiAgZ2V0IGRpcmVjdGlvbigpOiBEaXJlY3Rpb24ge1xuICAgIHJldHVybiB0aGlzLmRpcmVjdGlvblNvdXJjZS52YWx1ZTtcbiAgfVxuXG4gIC8qKiBXaGV0aGVyIHRoZSBjdXJyZW50IGRpcmVjdGlvbiBpcyBleHBsaWNpdGx5IHJpZ2h0LXRvLWxlZnQuICovXG4gIGdldCBpc1J0bCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5kaXJlY3Rpb25Tb3VyY2UudmFsdWUgPT09ICdydGwnO1xuICB9XG5cbiAgLyoqIFNldHMgdGhlIGN1cnJlbnQgZGlyZWN0aW9uLCBlbWl0dGluZyBvbmx5IHdoZW4gaXQgYWN0dWFsbHkgY2hhbmdlcy4gKi9cbiAgc2V0RGlyZWN0aW9uKGRpcmVjdGlvbjogRGlyZWN0aW9uKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlyZWN0aW9uU291cmNlLnZhbHVlICE9PSBkaXJlY3Rpb24pIHRoaXMuZGlyZWN0aW9uU291cmNlLm5leHQoZGlyZWN0aW9uKTtcbiAgfVxufVxuXG4vKipcbiAqIFNldHMgdGhlIGBkaXJgIGF0dHJpYnV0ZSBvbiBpdHMgaG9zdCBhbmQgcHVibGlzaGVzIHRoYXQgZGlyZWN0aW9uIHRvXG4gKiBgRGlyZWN0aW9uU2VydmljZWAsIHNvIGEgd2hvbGUgY2hhdCBzdXJmYWNlIGNhbiBiZSBmbGlwcGVkIHRvIFJUTCBmcm9tIG9uZVxuICogcGxhY2UuIFB1dCBpdCBvbiB0aGUgb3V0ZXJtb3N0IGVsZW1lbnQgb2YgdGhlIHN1YnRyZWUgeW91IHdhbnQgdG8gZmxpcC5cbiAqIEBuZXdcbiAqL1xuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW3RvbGxlRGlyZWN0aW9uXScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG59KVxuZXhwb3J0IGNsYXNzIERpcmVjdGlvbkRpcmVjdGl2ZSBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XG4gIC8qKiBXcml0aW5nIGRpcmVjdGlvbiBhcHBsaWVkIHRvIHRoZSBob3N0J3MgYGRpcmAgYXR0cmlidXRlLiBAZGVmYXVsdCAnbHRyJyAqL1xuICBASW5wdXQoKSB0b2xsZURpcmVjdGlvbjogRGlyZWN0aW9uID0gJ2x0cic7XG4gIC8qKiBXaGV0aGVyIHRvIHB1Ymxpc2ggdGhpcyBkaXJlY3Rpb24gdG8gdGhlIGFwcC13aWRlIGBEaXJlY3Rpb25TZXJ2aWNlYC4gQGRlZmF1bHQgdHJ1ZSAqL1xuICBASW5wdXQoKSB0b2xsZURpcmVjdGlvblB1Ymxpc2ggPSB0cnVlO1xuXG4gIC8qKiBFbWl0dGVkIHdpdGggdGhlIGRpcmVjdGlvbiB3aGVuZXZlciBpdCBjaGFuZ2VzLiAqL1xuICBAT3V0cHV0KCkgZGlyZWN0aW9uQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxEaXJlY3Rpb24+KCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBzZXJ2aWNlID0gaW5qZWN0KERpcmVjdGlvblNlcnZpY2UpO1xuXG4gIC8qKiBUaGUgcmVzb2x2ZWQgYGRpcmAgYXR0cmlidXRlIHZhbHVlIHdyaXR0ZW4gb250byB0aGUgaG9zdC4gKi9cbiAgQEhvc3RCaW5kaW5nKCdhdHRyLmRpcicpXG4gIGdldCBkaXIoKTogRGlyZWN0aW9uIHtcbiAgICByZXR1cm4gdGhpcy50b2xsZURpcmVjdGlvbiA/PyAnbHRyJztcbiAgfVxuXG4gIG5nT25DaGFuZ2VzKCk6IHZvaWQge1xuICAgIGNvbnN0IGRpcmVjdGlvbiA9IHRoaXMuZGlyO1xuICAgIGlmICh0aGlzLnRvbGxlRGlyZWN0aW9uUHVibGlzaCkgdGhpcy5zZXJ2aWNlLnNldERpcmVjdGlvbihkaXJlY3Rpb24pO1xuICAgIHRoaXMuZGlyZWN0aW9uQ2hhbmdlLmVtaXQoZGlyZWN0aW9uKTtcbiAgfVxufVxuIl19
|