@tolle_/tolle-ui 0.0.1-beta
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/README.md +35 -0
- package/esm2022/lib/accordion-item.component.mjs +78 -0
- package/esm2022/lib/accordion.component.mjs +60 -0
- package/esm2022/lib/badge.component.mjs +76 -0
- package/esm2022/lib/button-group.component.mjs +25 -0
- package/esm2022/lib/button.component.mjs +70 -0
- package/esm2022/lib/calendar.component.mjs +315 -0
- package/esm2022/lib/card.component.mjs +94 -0
- package/esm2022/lib/checkbox.component.mjs +100 -0
- package/esm2022/lib/data-table.component.mjs +332 -0
- package/esm2022/lib/date-picker.component.mjs +232 -0
- package/esm2022/lib/date-range-picker.component.mjs +208 -0
- package/esm2022/lib/input.component.mjs +134 -0
- package/esm2022/lib/masked-input.component.mjs +179 -0
- package/esm2022/lib/modal-ref.mjs +31 -0
- package/esm2022/lib/modal-stack.service.mjs +26 -0
- package/esm2022/lib/modal.component.mjs +98 -0
- package/esm2022/lib/modal.mjs +27 -0
- package/esm2022/lib/modal.service.mjs +65 -0
- package/esm2022/lib/multi-select.component.mjs +231 -0
- package/esm2022/lib/pagination.component.mjs +279 -0
- package/esm2022/lib/range-calendar.component.mjs +285 -0
- package/esm2022/lib/select-group.component.mjs +28 -0
- package/esm2022/lib/select-item.component.mjs +84 -0
- package/esm2022/lib/select-separator.component.mjs +24 -0
- package/esm2022/lib/select.component.mjs +261 -0
- package/esm2022/lib/select.service.mjs +21 -0
- package/esm2022/lib/skeleton.component.mjs +34 -0
- package/esm2022/lib/switch.component.mjs +133 -0
- package/esm2022/lib/toast.service.mjs +59 -0
- package/esm2022/lib/tolle-cell.directive.mjs +22 -0
- package/esm2022/lib/tolle-config.mjs +11 -0
- package/esm2022/lib/tooltip.directive.mjs +71 -0
- package/esm2022/lib/types/date-range.mjs +2 -0
- package/esm2022/lib/utils/cn.mjs +6 -0
- package/esm2022/public-api.mjs +36 -0
- package/esm2022/tolle_-tolle-ui.mjs +5 -0
- package/fesm2022/tolle_-tolle-ui.mjs +3553 -0
- package/fesm2022/tolle_-tolle-ui.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/accordion-item.component.d.ts +13 -0
- package/lib/accordion.component.d.ts +14 -0
- package/lib/badge.component.d.ts +14 -0
- package/lib/button-group.component.d.ts +8 -0
- package/lib/button.component.d.ts +16 -0
- package/lib/calendar.component.d.ts +35 -0
- package/lib/card.component.d.ts +32 -0
- package/lib/checkbox.component.d.ts +23 -0
- package/lib/data-table.component.d.ts +45 -0
- package/lib/date-picker.component.d.ts +35 -0
- package/lib/date-range-picker.component.d.ts +36 -0
- package/lib/input.component.d.ts +27 -0
- package/lib/masked-input.component.d.ts +36 -0
- package/lib/modal-ref.d.ts +16 -0
- package/lib/modal-stack.service.d.ts +12 -0
- package/lib/modal.component.d.ts +19 -0
- package/lib/modal.d.ts +29 -0
- package/lib/modal.service.d.ts +18 -0
- package/lib/multi-select.component.d.ts +47 -0
- package/lib/pagination.component.d.ts +36 -0
- package/lib/range-calendar.component.d.ts +37 -0
- package/lib/select-group.component.d.ts +8 -0
- package/lib/select-item.component.d.ts +18 -0
- package/lib/select-separator.component.d.ts +8 -0
- package/lib/select.component.d.ts +45 -0
- package/lib/select.service.d.ts +10 -0
- package/lib/skeleton.component.d.ts +10 -0
- package/lib/switch.component.d.ts +39 -0
- package/lib/toast.service.d.ts +24 -0
- package/lib/tolle-cell.directive.d.ts +9 -0
- package/lib/tolle-config.d.ts +9 -0
- package/lib/tooltip.directive.d.ts +15 -0
- package/lib/types/date-range.d.ts +4 -0
- package/lib/utils/cn.d.ts +2 -0
- package/package.json +32 -0
- package/public-api.d.ts +32 -0
- package/theme.css +211 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, inject, Input, Output } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { cn } from './utils/cn';
|
|
4
|
+
import { SelectItemComponent, SelectComponent } from '@tolle/ui';
|
|
5
|
+
import { FormsModule } from '@angular/forms';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
import * as i1 from "@angular/common";
|
|
8
|
+
import * as i2 from "@angular/forms";
|
|
9
|
+
export class PaginationComponent {
|
|
10
|
+
class = '';
|
|
11
|
+
showPageLinks = true;
|
|
12
|
+
showPageOptions = true;
|
|
13
|
+
showCurrentPageInfo = true;
|
|
14
|
+
currentPageInfoTemplate;
|
|
15
|
+
totalRecords = 0;
|
|
16
|
+
currentPageSize = 10;
|
|
17
|
+
currentPage = 1;
|
|
18
|
+
pageSizeOptions = [10, 20, 30, 50];
|
|
19
|
+
onPageNumberChange = new EventEmitter();
|
|
20
|
+
onPageSizeChange = new EventEmitter();
|
|
21
|
+
totalPages = 0;
|
|
22
|
+
first = 0;
|
|
23
|
+
last = 0;
|
|
24
|
+
displayPageIndex = [];
|
|
25
|
+
pageReport = '';
|
|
26
|
+
initialized = false;
|
|
27
|
+
cd = inject(ChangeDetectorRef);
|
|
28
|
+
cn = cn;
|
|
29
|
+
navBtnClass = 'h-8 w-8 p-0 flex items-center justify-center rounded-md border border-input bg-background hover:bg-accent hover:text-accent-foreground disabled:opacity-50 disabled:cursor-not-allowed';
|
|
30
|
+
ngOnInit() {
|
|
31
|
+
this.initializePagination();
|
|
32
|
+
}
|
|
33
|
+
ngOnChanges(changes) {
|
|
34
|
+
// Only re-init if meaningful data changes
|
|
35
|
+
if (changes['totalRecords'] || changes['currentPage'] || changes['currentPageSize']) {
|
|
36
|
+
this.initializePagination();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
initializePagination() {
|
|
40
|
+
this.calcPagination();
|
|
41
|
+
if (!this.initialized) {
|
|
42
|
+
this.initialized = true;
|
|
43
|
+
}
|
|
44
|
+
this.cd.detectChanges();
|
|
45
|
+
}
|
|
46
|
+
nextPage() {
|
|
47
|
+
if (this.totalPages > this.currentPage) {
|
|
48
|
+
this.currentPage++;
|
|
49
|
+
this.emitChange();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
previousPage() {
|
|
53
|
+
if (this.currentPage > 1) {
|
|
54
|
+
this.currentPage--;
|
|
55
|
+
this.emitChange();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
selectPage(page) {
|
|
59
|
+
if (this.currentPage === page)
|
|
60
|
+
return;
|
|
61
|
+
this.currentPage = page;
|
|
62
|
+
this.emitChange();
|
|
63
|
+
}
|
|
64
|
+
sizeChange(size) {
|
|
65
|
+
this.currentPageSize = size;
|
|
66
|
+
this.currentPage = 1; // Reset to page 1 on size change
|
|
67
|
+
this.emitChange();
|
|
68
|
+
}
|
|
69
|
+
emitChange() {
|
|
70
|
+
this.calcPagination();
|
|
71
|
+
this.onPageNumberChange.emit(this.currentPage);
|
|
72
|
+
this.onPageSizeChange.emit(this.currentPageSize);
|
|
73
|
+
this.cd.detectChanges();
|
|
74
|
+
}
|
|
75
|
+
calcPagination() {
|
|
76
|
+
this.totalPages = Math.ceil(this.totalRecords / this.currentPageSize) || 0;
|
|
77
|
+
// Bounds check
|
|
78
|
+
if (this.currentPage > this.totalPages && this.totalPages > 0) {
|
|
79
|
+
this.currentPage = this.totalPages;
|
|
80
|
+
}
|
|
81
|
+
this.first = this.totalRecords === 0 ? 0 : (this.currentPage - 1) * this.currentPageSize + 1;
|
|
82
|
+
this.last = Math.min(this.totalRecords, this.currentPage * this.currentPageSize);
|
|
83
|
+
// Calculate Sliding Window for Page Numbers (Max 5 visible)
|
|
84
|
+
const pages = Array.from({ length: this.totalPages }, (_, i) => i + 1);
|
|
85
|
+
if (this.totalPages <= 5) {
|
|
86
|
+
this.displayPageIndex = pages;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
let start = Math.max(0, this.currentPage - 3);
|
|
90
|
+
let end = start + 5;
|
|
91
|
+
if (end > this.totalPages) {
|
|
92
|
+
end = this.totalPages;
|
|
93
|
+
start = end - 5;
|
|
94
|
+
}
|
|
95
|
+
this.displayPageIndex = pages.slice(start, end);
|
|
96
|
+
}
|
|
97
|
+
// Template Parsing
|
|
98
|
+
if (this.currentPageInfoTemplate) {
|
|
99
|
+
this.pageReport = this.currentPageInfoTemplate.replace(/{first}|{last}|{totalRecords}|{currentPage}|{currentPageSize}|{totalPages}/g, (match) => {
|
|
100
|
+
switch (match) {
|
|
101
|
+
case '{first}': return `${this.first}`;
|
|
102
|
+
case '{last}': return `${this.last}`;
|
|
103
|
+
case '{totalRecords}': return `${this.totalRecords}`;
|
|
104
|
+
case '{totalPages}': return `${this.totalPages}`;
|
|
105
|
+
case '{currentPage}': return `${this.currentPage}`;
|
|
106
|
+
case '{currentPageSize}': return `${this.currentPageSize}`;
|
|
107
|
+
default: return match;
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
113
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: PaginationComponent, isStandalone: true, selector: "tolle-pagination", inputs: { class: "class", showPageLinks: "showPageLinks", showPageOptions: "showPageOptions", showCurrentPageInfo: "showCurrentPageInfo", currentPageInfoTemplate: "currentPageInfoTemplate", totalRecords: "totalRecords", currentPageSize: "currentPageSize", currentPage: "currentPage", pageSizeOptions: "pageSizeOptions" }, outputs: { onPageNumberChange: "onPageNumberChange", onPageSizeChange: "onPageSizeChange" }, usesOnChanges: true, ngImport: i0, template: `
|
|
114
|
+
<div [class]="cn('flex items-center justify-between px-2 py-4', class)">
|
|
115
|
+
|
|
116
|
+
<div *ngIf="showCurrentPageInfo" class="text-sm text-muted-foreground">
|
|
117
|
+
<ng-container *ngIf="currentPageInfoTemplate; else defaultReport">
|
|
118
|
+
{{ pageReport }}
|
|
119
|
+
</ng-container>
|
|
120
|
+
<ng-template #defaultReport>
|
|
121
|
+
Showing {{ first }} to {{ last }} of {{ totalRecords }} entries
|
|
122
|
+
</ng-template>
|
|
123
|
+
</div>
|
|
124
|
+
|
|
125
|
+
<div class="flex items-center space-x-6 lg:space-x-8">
|
|
126
|
+
|
|
127
|
+
<div *ngIf="showPageOptions" class="flex items-center space-x-2">
|
|
128
|
+
<p class="text-sm font-medium">Rows per page</p>
|
|
129
|
+
<tolle-select
|
|
130
|
+
class="w-[70px]"
|
|
131
|
+
size="sm"
|
|
132
|
+
[ngModel]="currentPageSize"
|
|
133
|
+
(ngModelChange)="sizeChange($event)"
|
|
134
|
+
>
|
|
135
|
+
<tolle-select-item *ngFor="let opt of pageSizeOptions" [value]="opt">
|
|
136
|
+
{{ opt }}
|
|
137
|
+
</tolle-select-item>
|
|
138
|
+
</tolle-select>
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<div class="flex items-center space-x-2">
|
|
142
|
+
<div *ngIf="!showPageLinks" class="flex w-[100px] items-center justify-center text-sm font-medium">
|
|
143
|
+
Page {{ currentPage }} of {{ totalPages }}
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
<div *ngIf="showPageLinks" class="flex items-center space-x-1">
|
|
147
|
+
<button
|
|
148
|
+
(click)="previousPage()"
|
|
149
|
+
[disabled]="currentPage === 1"
|
|
150
|
+
[class]="navBtnClass"
|
|
151
|
+
>
|
|
152
|
+
<i class="ri-arrow-left-s-line"></i>
|
|
153
|
+
</button>
|
|
154
|
+
|
|
155
|
+
<button
|
|
156
|
+
*ngFor="let page of displayPageIndex"
|
|
157
|
+
(click)="selectPage(page)"
|
|
158
|
+
[class]="cn(
|
|
159
|
+
'h-8 w-8 text-sm rounded-md flex items-center justify-center transition-colors',
|
|
160
|
+
currentPage === page
|
|
161
|
+
? 'bg-primary text-primary-foreground font-medium'
|
|
162
|
+
: 'hover:bg-accent hover:text-accent-foreground'
|
|
163
|
+
)"
|
|
164
|
+
>
|
|
165
|
+
{{ page }}
|
|
166
|
+
</button>
|
|
167
|
+
|
|
168
|
+
<button
|
|
169
|
+
(click)="nextPage()"
|
|
170
|
+
[disabled]="currentPage === totalPages || totalPages === 0"
|
|
171
|
+
[class]="navBtnClass"
|
|
172
|
+
>
|
|
173
|
+
<i class="ri-arrow-right-s-line"></i>
|
|
174
|
+
</button>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: SelectComponent, selector: "tolle-select", inputs: ["placeholder", "class", "disabled", "searchable", "size"] }, { kind: "component", type: SelectItemComponent, selector: "tolle-select-item", inputs: ["value", "class", "selected"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
180
|
+
}
|
|
181
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PaginationComponent, decorators: [{
|
|
182
|
+
type: Component,
|
|
183
|
+
args: [{
|
|
184
|
+
selector: 'tolle-pagination',
|
|
185
|
+
standalone: true,
|
|
186
|
+
imports: [CommonModule, SelectComponent, SelectItemComponent, FormsModule],
|
|
187
|
+
template: `
|
|
188
|
+
<div [class]="cn('flex items-center justify-between px-2 py-4', class)">
|
|
189
|
+
|
|
190
|
+
<div *ngIf="showCurrentPageInfo" class="text-sm text-muted-foreground">
|
|
191
|
+
<ng-container *ngIf="currentPageInfoTemplate; else defaultReport">
|
|
192
|
+
{{ pageReport }}
|
|
193
|
+
</ng-container>
|
|
194
|
+
<ng-template #defaultReport>
|
|
195
|
+
Showing {{ first }} to {{ last }} of {{ totalRecords }} entries
|
|
196
|
+
</ng-template>
|
|
197
|
+
</div>
|
|
198
|
+
|
|
199
|
+
<div class="flex items-center space-x-6 lg:space-x-8">
|
|
200
|
+
|
|
201
|
+
<div *ngIf="showPageOptions" class="flex items-center space-x-2">
|
|
202
|
+
<p class="text-sm font-medium">Rows per page</p>
|
|
203
|
+
<tolle-select
|
|
204
|
+
class="w-[70px]"
|
|
205
|
+
size="sm"
|
|
206
|
+
[ngModel]="currentPageSize"
|
|
207
|
+
(ngModelChange)="sizeChange($event)"
|
|
208
|
+
>
|
|
209
|
+
<tolle-select-item *ngFor="let opt of pageSizeOptions" [value]="opt">
|
|
210
|
+
{{ opt }}
|
|
211
|
+
</tolle-select-item>
|
|
212
|
+
</tolle-select>
|
|
213
|
+
</div>
|
|
214
|
+
|
|
215
|
+
<div class="flex items-center space-x-2">
|
|
216
|
+
<div *ngIf="!showPageLinks" class="flex w-[100px] items-center justify-center text-sm font-medium">
|
|
217
|
+
Page {{ currentPage }} of {{ totalPages }}
|
|
218
|
+
</div>
|
|
219
|
+
|
|
220
|
+
<div *ngIf="showPageLinks" class="flex items-center space-x-1">
|
|
221
|
+
<button
|
|
222
|
+
(click)="previousPage()"
|
|
223
|
+
[disabled]="currentPage === 1"
|
|
224
|
+
[class]="navBtnClass"
|
|
225
|
+
>
|
|
226
|
+
<i class="ri-arrow-left-s-line"></i>
|
|
227
|
+
</button>
|
|
228
|
+
|
|
229
|
+
<button
|
|
230
|
+
*ngFor="let page of displayPageIndex"
|
|
231
|
+
(click)="selectPage(page)"
|
|
232
|
+
[class]="cn(
|
|
233
|
+
'h-8 w-8 text-sm rounded-md flex items-center justify-center transition-colors',
|
|
234
|
+
currentPage === page
|
|
235
|
+
? 'bg-primary text-primary-foreground font-medium'
|
|
236
|
+
: 'hover:bg-accent hover:text-accent-foreground'
|
|
237
|
+
)"
|
|
238
|
+
>
|
|
239
|
+
{{ page }}
|
|
240
|
+
</button>
|
|
241
|
+
|
|
242
|
+
<button
|
|
243
|
+
(click)="nextPage()"
|
|
244
|
+
[disabled]="currentPage === totalPages || totalPages === 0"
|
|
245
|
+
[class]="navBtnClass"
|
|
246
|
+
>
|
|
247
|
+
<i class="ri-arrow-right-s-line"></i>
|
|
248
|
+
</button>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
`,
|
|
254
|
+
changeDetection: ChangeDetectionStrategy.OnPush
|
|
255
|
+
}]
|
|
256
|
+
}], propDecorators: { class: [{
|
|
257
|
+
type: Input
|
|
258
|
+
}], showPageLinks: [{
|
|
259
|
+
type: Input
|
|
260
|
+
}], showPageOptions: [{
|
|
261
|
+
type: Input
|
|
262
|
+
}], showCurrentPageInfo: [{
|
|
263
|
+
type: Input
|
|
264
|
+
}], currentPageInfoTemplate: [{
|
|
265
|
+
type: Input
|
|
266
|
+
}], totalRecords: [{
|
|
267
|
+
type: Input
|
|
268
|
+
}], currentPageSize: [{
|
|
269
|
+
type: Input
|
|
270
|
+
}], currentPage: [{
|
|
271
|
+
type: Input
|
|
272
|
+
}], pageSizeOptions: [{
|
|
273
|
+
type: Input
|
|
274
|
+
}], onPageNumberChange: [{
|
|
275
|
+
type: Output
|
|
276
|
+
}], onPageSizeChange: [{
|
|
277
|
+
type: Output
|
|
278
|
+
}] } });
|
|
279
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdGlvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy90b2xsZS9zcmMvbGliL3BhZ2luYXRpb24uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFHTCxNQUFNLEVBRVAsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDaEMsT0FBTyxFQUFDLG1CQUFtQixFQUFFLGVBQWUsRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUMvRCxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7Ozs7QUEyRTNDLE1BQU0sT0FBTyxtQkFBbUI7SUFDckIsS0FBSyxHQUFHLEVBQUUsQ0FBQztJQUNYLGFBQWEsR0FBRyxJQUFJLENBQUM7SUFDckIsZUFBZSxHQUFHLElBQUksQ0FBQztJQUN2QixtQkFBbUIsR0FBRyxJQUFJLENBQUM7SUFDM0IsdUJBQXVCLENBQVU7SUFFakMsWUFBWSxHQUFHLENBQUMsQ0FBQztJQUNqQixlQUFlLEdBQUcsRUFBRSxDQUFDO0lBQ3JCLFdBQVcsR0FBRyxDQUFDLENBQUM7SUFDaEIsZUFBZSxHQUFhLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFNUMsa0JBQWtCLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztJQUNoRCxnQkFBZ0IsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO0lBRXhELFVBQVUsR0FBRyxDQUFDLENBQUM7SUFDZixLQUFLLEdBQUcsQ0FBQyxDQUFDO0lBQ1YsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUNULGdCQUFnQixHQUFhLEVBQUUsQ0FBQztJQUNoQyxVQUFVLEdBQUcsRUFBRSxDQUFDO0lBRVIsV0FBVyxHQUFHLEtBQUssQ0FBQztJQUNwQixFQUFFLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7SUFDN0IsRUFBRSxHQUFHLEVBQUUsQ0FBQztJQUVsQixXQUFXLEdBQUcsd0xBQXdMLENBQUM7SUFFdk0sUUFBUTtRQUNOLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO0lBQzlCLENBQUM7SUFFRCxXQUFXLENBQUMsT0FBc0I7UUFDaEMsMENBQTBDO1FBQzFDLElBQUksT0FBTyxDQUFDLGNBQWMsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxhQUFhLENBQUMsSUFBSSxPQUFPLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUFDO1lBQ3BGLElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQzlCLENBQUM7SUFDSCxDQUFDO0lBRU8sb0JBQW9CO1FBQzFCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN0QixJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3RCLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO1FBQzFCLENBQUM7UUFDRCxJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFRCxRQUFRO1FBQ04sSUFBSSxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN2QyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ3BCLENBQUM7SUFDSCxDQUFDO0lBRUQsWUFBWTtRQUNWLElBQUksSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ3BCLENBQUM7SUFDSCxDQUFDO0lBRUQsVUFBVSxDQUFDLElBQVk7UUFDckIsSUFBSSxJQUFJLENBQUMsV0FBVyxLQUFLLElBQUk7WUFBRSxPQUFPO1FBQ3RDLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO1FBQ3hCLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUNwQixDQUFDO0lBRUQsVUFBVSxDQUFDLElBQVk7UUFDckIsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUM7UUFDNUIsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUMsQ0FBQyxpQ0FBaUM7UUFDdkQsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFFTyxVQUFVO1FBQ2hCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN0QixJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUMvQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFTyxjQUFjO1FBQ3BCLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFM0UsZUFBZTtRQUNmLElBQUksSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsVUFBVSxJQUFJLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDOUQsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDO1FBQ3JDLENBQUM7UUFFRCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsZUFBZSxHQUFHLENBQUMsQ0FBQztRQUM3RixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUVqRiw0REFBNEQ7UUFDNUQsTUFBTSxLQUFLLEdBQWEsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFFakYsSUFBSSxJQUFJLENBQUMsVUFBVSxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3pCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7UUFDaEMsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQzlDLElBQUksR0FBRyxHQUFHLEtBQUssR0FBRyxDQUFDLENBQUM7WUFFcEIsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUMxQixHQUFHLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQztnQkFDdEIsS0FBSyxHQUFHLEdBQUcsR0FBRyxDQUFDLENBQUM7WUFDbEIsQ0FBQztZQUNELElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNsRCxDQUFDO1FBRUQsbUJBQW1CO1FBQ25CLElBQUksSUFBSSxDQUFDLHVCQUF1QixFQUFFLENBQUM7WUFDakMsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsdUJBQXVCLENBQUMsT0FBTyxDQUNwRCw2RUFBNkUsRUFDN0UsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDUixRQUFRLEtBQUssRUFBRSxDQUFDO29CQUNkLEtBQUssU0FBUyxDQUFDLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztvQkFDdkMsS0FBSyxRQUFRLENBQUMsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO29CQUNyQyxLQUFLLGdCQUFnQixDQUFDLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztvQkFDckQsS0FBSyxjQUFjLENBQUMsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO29CQUNqRCxLQUFLLGVBQWUsQ0FBQyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7b0JBQ25ELEtBQUssbUJBQW1CLENBQUMsQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO29CQUMzRCxPQUFPLENBQUMsQ0FBQyxPQUFPLEtBQUssQ0FBQztnQkFDeEIsQ0FBQztZQUNILENBQUMsQ0FDRixDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7d0dBM0hVLG1CQUFtQjs0RkFBbkIsbUJBQW1CLGdnQkFyRXBCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrRVQsMkRBbkVTLFlBQVksZ1FBQUUsZUFBZSw2SEFBRSxtQkFBbUIscUdBQUUsV0FBVzs7NEZBc0U5RCxtQkFBbUI7a0JBekUvQixTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxrQkFBa0I7b0JBQzVCLFVBQVUsRUFBRSxJQUFJO29CQUNoQixPQUFPLEVBQUUsQ0FBQyxZQUFZLEVBQUUsZUFBZSxFQUFFLG1CQUFtQixFQUFFLFdBQVcsQ0FBQztvQkFDMUUsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrRVQ7b0JBQ0QsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07aUJBQ2hEOzhCQUVVLEtBQUs7c0JBQWIsS0FBSztnQkFDRyxhQUFhO3NCQUFyQixLQUFLO2dCQUNHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBQ0csbUJBQW1CO3NCQUEzQixLQUFLO2dCQUNHLHVCQUF1QjtzQkFBL0IsS0FBSztnQkFFRyxZQUFZO3NCQUFwQixLQUFLO2dCQUNHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBQ0csV0FBVztzQkFBbkIsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUVJLGtCQUFrQjtzQkFBM0IsTUFBTTtnQkFDRyxnQkFBZ0I7c0JBQXpCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBpbmplY3QsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBTaW1wbGVDaGFuZ2VzXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IGNuIH0gZnJvbSAnLi91dGlscy9jbic7XG5pbXBvcnQge1NlbGVjdEl0ZW1Db21wb25lbnQsIFNlbGVjdENvbXBvbmVudH0gZnJvbSAnQHRvbGxlL3VpJztcbmltcG9ydCB7Rm9ybXNNb2R1bGV9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9sbGUtcGFnaW5hdGlvbicsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIFNlbGVjdENvbXBvbmVudCwgU2VsZWN0SXRlbUNvbXBvbmVudCwgRm9ybXNNb2R1bGVdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgW2NsYXNzXT1cImNuKCdmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gcHgtMiBweS00JywgY2xhc3MpXCI+XG5cbiAgICAgIDxkaXYgKm5nSWY9XCJzaG93Q3VycmVudFBhZ2VJbmZvXCIgY2xhc3M9XCJ0ZXh0LXNtIHRleHQtbXV0ZWQtZm9yZWdyb3VuZFwiPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiY3VycmVudFBhZ2VJbmZvVGVtcGxhdGU7IGVsc2UgZGVmYXVsdFJlcG9ydFwiPlxuICAgICAgICAgIHt7IHBhZ2VSZXBvcnQgfX1cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjZGVmYXVsdFJlcG9ydD5cbiAgICAgICAgICBTaG93aW5nIHt7IGZpcnN0IH19IHRvIHt7IGxhc3QgfX0gb2Yge3sgdG90YWxSZWNvcmRzIH19IGVudHJpZXNcbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgc3BhY2UteC02IGxnOnNwYWNlLXgtOFwiPlxuXG4gICAgICAgIDxkaXYgKm5nSWY9XCJzaG93UGFnZU9wdGlvbnNcIiBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIHNwYWNlLXgtMlwiPlxuICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1zbSBmb250LW1lZGl1bVwiPlJvd3MgcGVyIHBhZ2U8L3A+XG4gICAgICAgICAgPHRvbGxlLXNlbGVjdFxuICAgICAgICAgICAgY2xhc3M9XCJ3LVs3MHB4XVwiXG4gICAgICAgICAgICBzaXplPVwic21cIlxuICAgICAgICAgICAgW25nTW9kZWxdPVwiY3VycmVudFBhZ2VTaXplXCJcbiAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cInNpemVDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPHRvbGxlLXNlbGVjdC1pdGVtICpuZ0Zvcj1cImxldCBvcHQgb2YgcGFnZVNpemVPcHRpb25zXCIgW3ZhbHVlXT1cIm9wdFwiPlxuICAgICAgICAgICAgICB7eyBvcHQgfX1cbiAgICAgICAgICAgIDwvdG9sbGUtc2VsZWN0LWl0ZW0+XG4gICAgICAgICAgPC90b2xsZS1zZWxlY3Q+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBzcGFjZS14LTJcIj5cbiAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIXNob3dQYWdlTGlua3NcIiBjbGFzcz1cImZsZXggdy1bMTAwcHhdIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciB0ZXh0LXNtIGZvbnQtbWVkaXVtXCI+XG4gICAgICAgICAgICBQYWdlIHt7IGN1cnJlbnRQYWdlIH19IG9mIHt7IHRvdGFsUGFnZXMgfX1cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxkaXYgKm5nSWY9XCJzaG93UGFnZUxpbmtzXCIgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBzcGFjZS14LTFcIj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgKGNsaWNrKT1cInByZXZpb3VzUGFnZSgpXCJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImN1cnJlbnRQYWdlID09PSAxXCJcbiAgICAgICAgICAgICAgW2NsYXNzXT1cIm5hdkJ0bkNsYXNzXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPGkgY2xhc3M9XCJyaS1hcnJvdy1sZWZ0LXMtbGluZVwiPjwvaT5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBwYWdlIG9mIGRpc3BsYXlQYWdlSW5kZXhcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0UGFnZShwYWdlKVwiXG4gICAgICAgICAgICAgIFtjbGFzc109XCJjbihcbiAgICAgICAgICAgICAgICAnaC04IHctOCB0ZXh0LXNtIHJvdW5kZWQtbWQgZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgdHJhbnNpdGlvbi1jb2xvcnMnLFxuICAgICAgICAgICAgICAgIGN1cnJlbnRQYWdlID09PSBwYWdlXG4gICAgICAgICAgICAgICAgICA/ICdiZy1wcmltYXJ5IHRleHQtcHJpbWFyeS1mb3JlZ3JvdW5kIGZvbnQtbWVkaXVtJ1xuICAgICAgICAgICAgICAgICAgOiAnaG92ZXI6YmctYWNjZW50IGhvdmVyOnRleHQtYWNjZW50LWZvcmVncm91bmQnXG4gICAgICAgICAgICAgIClcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7eyBwYWdlIH19XG4gICAgICAgICAgICA8L2J1dHRvbj5cblxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAoY2xpY2spPVwibmV4dFBhZ2UoKVwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJjdXJyZW50UGFnZSA9PT0gdG90YWxQYWdlcyB8fCB0b3RhbFBhZ2VzID09PSAwXCJcbiAgICAgICAgICAgICAgW2NsYXNzXT1cIm5hdkJ0bkNsYXNzXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPGkgY2xhc3M9XCJyaS1hcnJvdy1yaWdodC1zLWxpbmVcIj48L2k+XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgUGFnaW5hdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcbiAgQElucHV0KCkgY2xhc3MgPSAnJztcbiAgQElucHV0KCkgc2hvd1BhZ2VMaW5rcyA9IHRydWU7XG4gIEBJbnB1dCgpIHNob3dQYWdlT3B0aW9ucyA9IHRydWU7XG4gIEBJbnB1dCgpIHNob3dDdXJyZW50UGFnZUluZm8gPSB0cnVlO1xuICBASW5wdXQoKSBjdXJyZW50UGFnZUluZm9UZW1wbGF0ZT86IHN0cmluZztcblxuICBASW5wdXQoKSB0b3RhbFJlY29yZHMgPSAwO1xuICBASW5wdXQoKSBjdXJyZW50UGFnZVNpemUgPSAxMDtcbiAgQElucHV0KCkgY3VycmVudFBhZ2UgPSAxO1xuICBASW5wdXQoKSBwYWdlU2l6ZU9wdGlvbnM6IG51bWJlcltdID0gWzEwLCAyMCwgMzAsIDUwXTtcblxuICBAT3V0cHV0KCkgb25QYWdlTnVtYmVyQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XG4gIEBPdXRwdXQoKSBvblBhZ2VTaXplQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XG5cbiAgdG90YWxQYWdlcyA9IDA7XG4gIGZpcnN0ID0gMDtcbiAgbGFzdCA9IDA7XG4gIGRpc3BsYXlQYWdlSW5kZXg6IG51bWJlcltdID0gW107XG4gIHBhZ2VSZXBvcnQgPSAnJztcblxuICBwcml2YXRlIGluaXRpYWxpemVkID0gZmFsc2U7XG4gIHByaXZhdGUgY2QgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xuICBwcm90ZWN0ZWQgY24gPSBjbjtcblxuICBuYXZCdG5DbGFzcyA9ICdoLTggdy04IHAtMCBmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciByb3VuZGVkLW1kIGJvcmRlciBib3JkZXItaW5wdXQgYmctYmFja2dyb3VuZCBob3ZlcjpiZy1hY2NlbnQgaG92ZXI6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCBkaXNhYmxlZDpvcGFjaXR5LTUwIGRpc2FibGVkOmN1cnNvci1ub3QtYWxsb3dlZCc7XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5pbml0aWFsaXplUGFnaW5hdGlvbigpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIC8vIE9ubHkgcmUtaW5pdCBpZiBtZWFuaW5nZnVsIGRhdGEgY2hhbmdlc1xuICAgIGlmIChjaGFuZ2VzWyd0b3RhbFJlY29yZHMnXSB8fCBjaGFuZ2VzWydjdXJyZW50UGFnZSddIHx8IGNoYW5nZXNbJ2N1cnJlbnRQYWdlU2l6ZSddKSB7XG4gICAgICB0aGlzLmluaXRpYWxpemVQYWdpbmF0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBpbml0aWFsaXplUGFnaW5hdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLmNhbGNQYWdpbmF0aW9uKCk7XG4gICAgaWYgKCF0aGlzLmluaXRpYWxpemVkKSB7XG4gICAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB9XG4gICAgdGhpcy5jZC5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICBuZXh0UGFnZSgpIHtcbiAgICBpZiAodGhpcy50b3RhbFBhZ2VzID4gdGhpcy5jdXJyZW50UGFnZSkge1xuICAgICAgdGhpcy5jdXJyZW50UGFnZSsrO1xuICAgICAgdGhpcy5lbWl0Q2hhbmdlKCk7XG4gICAgfVxuICB9XG5cbiAgcHJldmlvdXNQYWdlKCkge1xuICAgIGlmICh0aGlzLmN1cnJlbnRQYWdlID4gMSkge1xuICAgICAgdGhpcy5jdXJyZW50UGFnZS0tO1xuICAgICAgdGhpcy5lbWl0Q2hhbmdlKCk7XG4gICAgfVxuICB9XG5cbiAgc2VsZWN0UGFnZShwYWdlOiBudW1iZXIpIHtcbiAgICBpZiAodGhpcy5jdXJyZW50UGFnZSA9PT0gcGFnZSkgcmV0dXJuO1xuICAgIHRoaXMuY3VycmVudFBhZ2UgPSBwYWdlO1xuICAgIHRoaXMuZW1pdENoYW5nZSgpO1xuICB9XG5cbiAgc2l6ZUNoYW5nZShzaXplOiBudW1iZXIpIHtcbiAgICB0aGlzLmN1cnJlbnRQYWdlU2l6ZSA9IHNpemU7XG4gICAgdGhpcy5jdXJyZW50UGFnZSA9IDE7IC8vIFJlc2V0IHRvIHBhZ2UgMSBvbiBzaXplIGNoYW5nZVxuICAgIHRoaXMuZW1pdENoYW5nZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBlbWl0Q2hhbmdlKCk6IHZvaWQge1xuICAgIHRoaXMuY2FsY1BhZ2luYXRpb24oKTtcbiAgICB0aGlzLm9uUGFnZU51bWJlckNoYW5nZS5lbWl0KHRoaXMuY3VycmVudFBhZ2UpO1xuICAgIHRoaXMub25QYWdlU2l6ZUNoYW5nZS5lbWl0KHRoaXMuY3VycmVudFBhZ2VTaXplKTtcbiAgICB0aGlzLmNkLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuXG4gIHByaXZhdGUgY2FsY1BhZ2luYXRpb24oKTogdm9pZCB7XG4gICAgdGhpcy50b3RhbFBhZ2VzID0gTWF0aC5jZWlsKHRoaXMudG90YWxSZWNvcmRzIC8gdGhpcy5jdXJyZW50UGFnZVNpemUpIHx8IDA7XG5cbiAgICAvLyBCb3VuZHMgY2hlY2tcbiAgICBpZiAodGhpcy5jdXJyZW50UGFnZSA+IHRoaXMudG90YWxQYWdlcyAmJiB0aGlzLnRvdGFsUGFnZXMgPiAwKSB7XG4gICAgICB0aGlzLmN1cnJlbnRQYWdlID0gdGhpcy50b3RhbFBhZ2VzO1xuICAgIH1cblxuICAgIHRoaXMuZmlyc3QgPSB0aGlzLnRvdGFsUmVjb3JkcyA9PT0gMCA/IDAgOiAodGhpcy5jdXJyZW50UGFnZSAtIDEpICogdGhpcy5jdXJyZW50UGFnZVNpemUgKyAxO1xuICAgIHRoaXMubGFzdCA9IE1hdGgubWluKHRoaXMudG90YWxSZWNvcmRzLCB0aGlzLmN1cnJlbnRQYWdlICogdGhpcy5jdXJyZW50UGFnZVNpemUpO1xuXG4gICAgLy8gQ2FsY3VsYXRlIFNsaWRpbmcgV2luZG93IGZvciBQYWdlIE51bWJlcnMgKE1heCA1IHZpc2libGUpXG4gICAgY29uc3QgcGFnZXM6IG51bWJlcltdID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogdGhpcy50b3RhbFBhZ2VzIH0sIChfLCBpKSA9PiBpICsgMSk7XG5cbiAgICBpZiAodGhpcy50b3RhbFBhZ2VzIDw9IDUpIHtcbiAgICAgIHRoaXMuZGlzcGxheVBhZ2VJbmRleCA9IHBhZ2VzO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgc3RhcnQgPSBNYXRoLm1heCgwLCB0aGlzLmN1cnJlbnRQYWdlIC0gMyk7XG4gICAgICBsZXQgZW5kID0gc3RhcnQgKyA1O1xuXG4gICAgICBpZiAoZW5kID4gdGhpcy50b3RhbFBhZ2VzKSB7XG4gICAgICAgIGVuZCA9IHRoaXMudG90YWxQYWdlcztcbiAgICAgICAgc3RhcnQgPSBlbmQgLSA1O1xuICAgICAgfVxuICAgICAgdGhpcy5kaXNwbGF5UGFnZUluZGV4ID0gcGFnZXMuc2xpY2Uoc3RhcnQsIGVuZCk7XG4gICAgfVxuXG4gICAgLy8gVGVtcGxhdGUgUGFyc2luZ1xuICAgIGlmICh0aGlzLmN1cnJlbnRQYWdlSW5mb1RlbXBsYXRlKSB7XG4gICAgICB0aGlzLnBhZ2VSZXBvcnQgPSB0aGlzLmN1cnJlbnRQYWdlSW5mb1RlbXBsYXRlLnJlcGxhY2UoXG4gICAgICAgIC97Zmlyc3R9fHtsYXN0fXx7dG90YWxSZWNvcmRzfXx7Y3VycmVudFBhZ2V9fHtjdXJyZW50UGFnZVNpemV9fHt0b3RhbFBhZ2VzfS9nLFxuICAgICAgICAobWF0Y2gpID0+IHtcbiAgICAgICAgICBzd2l0Y2ggKG1hdGNoKSB7XG4gICAgICAgICAgICBjYXNlICd7Zmlyc3R9JzogcmV0dXJuIGAke3RoaXMuZmlyc3R9YDtcbiAgICAgICAgICAgIGNhc2UgJ3tsYXN0fSc6IHJldHVybiBgJHt0aGlzLmxhc3R9YDtcbiAgICAgICAgICAgIGNhc2UgJ3t0b3RhbFJlY29yZHN9JzogcmV0dXJuIGAke3RoaXMudG90YWxSZWNvcmRzfWA7XG4gICAgICAgICAgICBjYXNlICd7dG90YWxQYWdlc30nOiByZXR1cm4gYCR7dGhpcy50b3RhbFBhZ2VzfWA7XG4gICAgICAgICAgICBjYXNlICd7Y3VycmVudFBhZ2V9JzogcmV0dXJuIGAke3RoaXMuY3VycmVudFBhZ2V9YDtcbiAgICAgICAgICAgIGNhc2UgJ3tjdXJyZW50UGFnZVNpemV9JzogcmV0dXJuIGAke3RoaXMuY3VycmVudFBhZ2VTaXplfWA7XG4gICAgICAgICAgICBkZWZhdWx0OiByZXR1cm4gbWF0Y2g7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { Component, Input, forwardRef, Output, EventEmitter } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
|
+
import { addMonths, subMonths, startOfMonth, endOfMonth, startOfWeek, endOfWeek, eachDayOfInterval, isSameMonth, isSameDay, isToday, setMonth, setYear, addYears, subYears, isBefore, startOfDay, isWithinInterval } from 'date-fns';
|
|
5
|
+
import { cn } from './utils/cn';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
import * as i1 from "@angular/common";
|
|
8
|
+
export class RangeCalendarComponent {
|
|
9
|
+
class = '';
|
|
10
|
+
disablePastDates = false;
|
|
11
|
+
rangeSelect = new EventEmitter(); // Emits whenever selection changes
|
|
12
|
+
currentView = 'date';
|
|
13
|
+
viewDate = new Date();
|
|
14
|
+
// The Range Value
|
|
15
|
+
value = { start: null, end: null };
|
|
16
|
+
weekDays = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
|
|
17
|
+
daysInMonth = [];
|
|
18
|
+
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
19
|
+
years = [];
|
|
20
|
+
navBtnClass = cn('h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100 border border-input rounded-md flex items-center justify-center hover:bg-accent hover:text-accent-foreground transition-all');
|
|
21
|
+
onTouched = () => { };
|
|
22
|
+
onChange = () => { };
|
|
23
|
+
cn = cn;
|
|
24
|
+
ngOnInit() {
|
|
25
|
+
this.generateDays();
|
|
26
|
+
this.generateYears();
|
|
27
|
+
}
|
|
28
|
+
// --- Date Generation Logic (Same as Calendar) ---
|
|
29
|
+
generateDays() {
|
|
30
|
+
const start = startOfWeek(startOfMonth(this.viewDate));
|
|
31
|
+
const end = endOfWeek(endOfMonth(this.viewDate));
|
|
32
|
+
this.daysInMonth = eachDayOfInterval({ start, end });
|
|
33
|
+
}
|
|
34
|
+
generateYears() {
|
|
35
|
+
const currentYear = this.viewDate.getFullYear();
|
|
36
|
+
this.years = Array.from({ length: 16 }, (_, i) => currentYear - 6 + i);
|
|
37
|
+
}
|
|
38
|
+
setView(view) {
|
|
39
|
+
this.currentView = view;
|
|
40
|
+
if (view === 'year')
|
|
41
|
+
this.generateYears();
|
|
42
|
+
}
|
|
43
|
+
prev() {
|
|
44
|
+
if (this.currentView === 'date') {
|
|
45
|
+
this.viewDate = subMonths(this.viewDate, 1);
|
|
46
|
+
this.generateDays();
|
|
47
|
+
}
|
|
48
|
+
else if (this.currentView === 'year') {
|
|
49
|
+
this.viewDate = subYears(this.viewDate, 16);
|
|
50
|
+
this.generateYears();
|
|
51
|
+
}
|
|
52
|
+
else if (this.currentView === 'month') {
|
|
53
|
+
this.viewDate = subYears(this.viewDate, 1);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
next() {
|
|
57
|
+
if (this.currentView === 'date') {
|
|
58
|
+
this.viewDate = addMonths(this.viewDate, 1);
|
|
59
|
+
this.generateDays();
|
|
60
|
+
}
|
|
61
|
+
else if (this.currentView === 'year') {
|
|
62
|
+
this.viewDate = addYears(this.viewDate, 16);
|
|
63
|
+
this.generateYears();
|
|
64
|
+
}
|
|
65
|
+
else if (this.currentView === 'month') {
|
|
66
|
+
this.viewDate = addYears(this.viewDate, 1);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// --- Range Selection Logic ---
|
|
70
|
+
selectDate(date) {
|
|
71
|
+
if (this.isDateDisabled(date))
|
|
72
|
+
return;
|
|
73
|
+
const { start, end } = this.value;
|
|
74
|
+
// 1. If start exists but end doesn't
|
|
75
|
+
if (start && !end) {
|
|
76
|
+
if (isBefore(date, start)) {
|
|
77
|
+
// User clicked earlier date -> Reset start
|
|
78
|
+
this.value = { start: date, end: null };
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// User clicked later date -> Complete range
|
|
82
|
+
this.value = { start, end: date };
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// 2. If neither exist OR both exist (reset)
|
|
86
|
+
else {
|
|
87
|
+
this.value = { start: date, end: null };
|
|
88
|
+
}
|
|
89
|
+
if (!isSameMonth(date, this.viewDate)) {
|
|
90
|
+
this.viewDate = date;
|
|
91
|
+
this.generateDays();
|
|
92
|
+
}
|
|
93
|
+
this.onChange(this.value);
|
|
94
|
+
this.rangeSelect.emit(this.value);
|
|
95
|
+
this.onTouched();
|
|
96
|
+
}
|
|
97
|
+
selectMonth(monthIndex) {
|
|
98
|
+
this.viewDate = setMonth(this.viewDate, monthIndex);
|
|
99
|
+
this.currentView = 'date';
|
|
100
|
+
this.generateDays();
|
|
101
|
+
}
|
|
102
|
+
selectYear(year) {
|
|
103
|
+
this.viewDate = setYear(this.viewDate, year);
|
|
104
|
+
this.currentView = 'date';
|
|
105
|
+
this.generateDays();
|
|
106
|
+
}
|
|
107
|
+
// --- Visual Styling for Range ---
|
|
108
|
+
getDayClass(date) {
|
|
109
|
+
const { start, end } = this.value;
|
|
110
|
+
const isOutside = !isSameMonth(date, this.viewDate);
|
|
111
|
+
const isDisabled = this.isDateDisabled(date);
|
|
112
|
+
// Range Checks
|
|
113
|
+
const isStart = start && isSameDay(date, start);
|
|
114
|
+
const isEnd = end && isSameDay(date, end);
|
|
115
|
+
const isInside = start && end && isWithinInterval(date, { start, end });
|
|
116
|
+
const isTodayDate = isToday(date);
|
|
117
|
+
return cn(
|
|
118
|
+
// Base: h-9 w-9, but we remove margins/rounding for the 'strip' effect
|
|
119
|
+
'h-9 w-9 p-0 font-normal text-sm transition-all flex items-center justify-center relative z-10',
|
|
120
|
+
// Default State (Not selected, Not disabled)
|
|
121
|
+
!isInside && !isStart && !isEnd && !isDisabled && 'hover:bg-accent hover:text-accent-foreground rounded-md',
|
|
122
|
+
// The "Caps": Start and End
|
|
123
|
+
(isStart || isEnd) && 'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground',
|
|
124
|
+
// The "Strip": Dates between start and end
|
|
125
|
+
isInside && !isStart && !isEnd && 'bg-accent text-accent-foreground rounded-none',
|
|
126
|
+
// Connecting the Caps to the Strip (Rectangular inside edges)
|
|
127
|
+
isStart && end && 'rounded-l-md rounded-r-none', isEnd && start && 'rounded-r-md rounded-l-none',
|
|
128
|
+
// If no end date yet, Start should be fully rounded
|
|
129
|
+
isStart && !end && 'rounded-md',
|
|
130
|
+
// Muted/Disabled logic
|
|
131
|
+
!isInside && isTodayDate && !isStart && !isEnd && 'bg-accent/50 text-accent-foreground rounded-md', (isOutside || isDisabled) && 'text-muted-foreground opacity-50', isDisabled && 'cursor-not-allowed');
|
|
132
|
+
}
|
|
133
|
+
isDateDisabled(date) {
|
|
134
|
+
return this.disablePastDates ? isBefore(date, startOfDay(new Date())) : false;
|
|
135
|
+
}
|
|
136
|
+
// --- CVA Implementation ---
|
|
137
|
+
writeValue(val) {
|
|
138
|
+
if (val) {
|
|
139
|
+
this.value = val;
|
|
140
|
+
if (val.start)
|
|
141
|
+
this.viewDate = val.start;
|
|
142
|
+
this.generateDays();
|
|
143
|
+
this.generateYears();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
registerOnChange(fn) { this.onChange = fn; }
|
|
147
|
+
registerOnTouched(fn) { this.onTouched = fn; }
|
|
148
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RangeCalendarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
149
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: RangeCalendarComponent, isStandalone: true, selector: "tolle-range-calendar", inputs: { class: "class", disablePastDates: "disablePastDates" }, outputs: { rangeSelect: "rangeSelect" }, providers: [
|
|
150
|
+
{
|
|
151
|
+
provide: NG_VALUE_ACCESSOR,
|
|
152
|
+
useExisting: forwardRef(() => RangeCalendarComponent),
|
|
153
|
+
multi: true
|
|
154
|
+
}
|
|
155
|
+
], ngImport: i0, template: `
|
|
156
|
+
<div [class]="cn('p-3 border rounded-md bg-background text-popover-foreground shadow-sm inline-block min-w-fit', class)">
|
|
157
|
+
|
|
158
|
+
<div class="flex items-center justify-between pt-1 pb-4 gap-2">
|
|
159
|
+
<div class="flex items-center gap-1">
|
|
160
|
+
<button type="button" (click)="setView('month')"
|
|
161
|
+
[class]="cn('text-sm font-semibold px-2 py-1 rounded transition-colors', currentView === 'month' ? 'bg-secondary text-secondary-foreground' : 'hover:bg-accent hover:text-accent-foreground')">
|
|
162
|
+
{{ viewDate | date: 'MMMM' }}
|
|
163
|
+
</button>
|
|
164
|
+
<button type="button" (click)="setView('year')"
|
|
165
|
+
[class]="cn('text-sm font-semibold px-2 py-1 rounded transition-colors', currentView === 'year' ? 'bg-secondary text-secondary-foreground' : 'hover:bg-accent hover:text-accent-foreground')">
|
|
166
|
+
{{ viewDate | date: 'yyyy' }}
|
|
167
|
+
</button>
|
|
168
|
+
</div>
|
|
169
|
+
<div class="flex items-center space-x-1">
|
|
170
|
+
<button type="button" (click)="prev()" [class]="navBtnClass"><i class="ri-arrow-left-s-line text-lg"></i></button>
|
|
171
|
+
<button type="button" (click)="next()" [class]="navBtnClass"><i class="ri-arrow-right-s-line text-lg"></i></button>
|
|
172
|
+
</div>
|
|
173
|
+
</div>
|
|
174
|
+
|
|
175
|
+
<div *ngIf="currentView === 'date'" class="space-y-2 animate-in fade-in zoom-in-95 duration-200">
|
|
176
|
+
<div class="grid grid-cols-7 gap-y-1 w-full">
|
|
177
|
+
<span *ngFor="let day of weekDays" class="text-[0.8rem] text-muted-foreground font-normal text-center w-9">
|
|
178
|
+
{{ day }}
|
|
179
|
+
</span>
|
|
180
|
+
</div>
|
|
181
|
+
<div class="grid grid-cols-7 gap-y-1 w-full">
|
|
182
|
+
<button
|
|
183
|
+
*ngFor="let date of daysInMonth"
|
|
184
|
+
type="button"
|
|
185
|
+
(click)="selectDate(date)"
|
|
186
|
+
[disabled]="isDateDisabled(date)"
|
|
187
|
+
[class]="getDayClass(date)"
|
|
188
|
+
>
|
|
189
|
+
{{ date | date: 'd' }}
|
|
190
|
+
</button>
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
|
|
194
|
+
<div *ngIf="currentView === 'month'" class="grid grid-cols-3 gap-2 w-64 animate-in fade-in zoom-in-95 duration-200">
|
|
195
|
+
<button *ngFor="let month of months; let i = index" type="button" (click)="selectMonth(i)"
|
|
196
|
+
[class]="cn('text-sm py-2.5 rounded-md hover:bg-accent hover:text-accent-foreground transition-colors', i === viewDate.getMonth() ? 'bg-primary text-primary-foreground' : '')">
|
|
197
|
+
{{ month }}
|
|
198
|
+
</button>
|
|
199
|
+
</div>
|
|
200
|
+
|
|
201
|
+
<div *ngIf="currentView === 'year'" class="grid grid-cols-4 gap-2 w-64 animate-in fade-in zoom-in-95 duration-200">
|
|
202
|
+
<button *ngFor="let year of years" type="button" (click)="selectYear(year)"
|
|
203
|
+
[class]="cn('text-sm py-2 rounded-md hover:bg-accent hover:text-accent-foreground transition-colors', year === viewDate.getFullYear() ? 'bg-primary text-primary-foreground' : '')">
|
|
204
|
+
{{ year }}
|
|
205
|
+
</button>
|
|
206
|
+
</div>
|
|
207
|
+
</div>
|
|
208
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }] });
|
|
209
|
+
}
|
|
210
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: RangeCalendarComponent, decorators: [{
|
|
211
|
+
type: Component,
|
|
212
|
+
args: [{
|
|
213
|
+
selector: 'tolle-range-calendar',
|
|
214
|
+
standalone: true,
|
|
215
|
+
imports: [CommonModule],
|
|
216
|
+
providers: [
|
|
217
|
+
{
|
|
218
|
+
provide: NG_VALUE_ACCESSOR,
|
|
219
|
+
useExisting: forwardRef(() => RangeCalendarComponent),
|
|
220
|
+
multi: true
|
|
221
|
+
}
|
|
222
|
+
],
|
|
223
|
+
template: `
|
|
224
|
+
<div [class]="cn('p-3 border rounded-md bg-background text-popover-foreground shadow-sm inline-block min-w-fit', class)">
|
|
225
|
+
|
|
226
|
+
<div class="flex items-center justify-between pt-1 pb-4 gap-2">
|
|
227
|
+
<div class="flex items-center gap-1">
|
|
228
|
+
<button type="button" (click)="setView('month')"
|
|
229
|
+
[class]="cn('text-sm font-semibold px-2 py-1 rounded transition-colors', currentView === 'month' ? 'bg-secondary text-secondary-foreground' : 'hover:bg-accent hover:text-accent-foreground')">
|
|
230
|
+
{{ viewDate | date: 'MMMM' }}
|
|
231
|
+
</button>
|
|
232
|
+
<button type="button" (click)="setView('year')"
|
|
233
|
+
[class]="cn('text-sm font-semibold px-2 py-1 rounded transition-colors', currentView === 'year' ? 'bg-secondary text-secondary-foreground' : 'hover:bg-accent hover:text-accent-foreground')">
|
|
234
|
+
{{ viewDate | date: 'yyyy' }}
|
|
235
|
+
</button>
|
|
236
|
+
</div>
|
|
237
|
+
<div class="flex items-center space-x-1">
|
|
238
|
+
<button type="button" (click)="prev()" [class]="navBtnClass"><i class="ri-arrow-left-s-line text-lg"></i></button>
|
|
239
|
+
<button type="button" (click)="next()" [class]="navBtnClass"><i class="ri-arrow-right-s-line text-lg"></i></button>
|
|
240
|
+
</div>
|
|
241
|
+
</div>
|
|
242
|
+
|
|
243
|
+
<div *ngIf="currentView === 'date'" class="space-y-2 animate-in fade-in zoom-in-95 duration-200">
|
|
244
|
+
<div class="grid grid-cols-7 gap-y-1 w-full">
|
|
245
|
+
<span *ngFor="let day of weekDays" class="text-[0.8rem] text-muted-foreground font-normal text-center w-9">
|
|
246
|
+
{{ day }}
|
|
247
|
+
</span>
|
|
248
|
+
</div>
|
|
249
|
+
<div class="grid grid-cols-7 gap-y-1 w-full">
|
|
250
|
+
<button
|
|
251
|
+
*ngFor="let date of daysInMonth"
|
|
252
|
+
type="button"
|
|
253
|
+
(click)="selectDate(date)"
|
|
254
|
+
[disabled]="isDateDisabled(date)"
|
|
255
|
+
[class]="getDayClass(date)"
|
|
256
|
+
>
|
|
257
|
+
{{ date | date: 'd' }}
|
|
258
|
+
</button>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
|
|
262
|
+
<div *ngIf="currentView === 'month'" class="grid grid-cols-3 gap-2 w-64 animate-in fade-in zoom-in-95 duration-200">
|
|
263
|
+
<button *ngFor="let month of months; let i = index" type="button" (click)="selectMonth(i)"
|
|
264
|
+
[class]="cn('text-sm py-2.5 rounded-md hover:bg-accent hover:text-accent-foreground transition-colors', i === viewDate.getMonth() ? 'bg-primary text-primary-foreground' : '')">
|
|
265
|
+
{{ month }}
|
|
266
|
+
</button>
|
|
267
|
+
</div>
|
|
268
|
+
|
|
269
|
+
<div *ngIf="currentView === 'year'" class="grid grid-cols-4 gap-2 w-64 animate-in fade-in zoom-in-95 duration-200">
|
|
270
|
+
<button *ngFor="let year of years" type="button" (click)="selectYear(year)"
|
|
271
|
+
[class]="cn('text-sm py-2 rounded-md hover:bg-accent hover:text-accent-foreground transition-colors', year === viewDate.getFullYear() ? 'bg-primary text-primary-foreground' : '')">
|
|
272
|
+
{{ year }}
|
|
273
|
+
</button>
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
`
|
|
277
|
+
}]
|
|
278
|
+
}], propDecorators: { class: [{
|
|
279
|
+
type: Input
|
|
280
|
+
}], disablePastDates: [{
|
|
281
|
+
type: Input
|
|
282
|
+
}], rangeSelect: [{
|
|
283
|
+
type: Output
|
|
284
|
+
}] } });
|
|
285
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmFuZ2UtY2FsZW5kYXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvdG9sbGUvc3JjL2xpYi9yYW5nZS1jYWxlbmRhci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQVUsVUFBVSxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0YsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RSxPQUFPLEVBQ0wsU0FBUyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUM5QyxXQUFXLEVBQUUsU0FBUyxFQUFFLGlCQUFpQixFQUFFLFdBQVcsRUFDdEQsU0FBUyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQ3pELFFBQVEsRUFBRSxVQUFVLEVBQUUsZ0JBQWdCLEVBQ3ZDLE1BQU0sVUFBVSxDQUFDO0FBQ2xCLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxZQUFZLENBQUM7OztBQXFFaEMsTUFBTSxPQUFPLHNCQUFzQjtJQUN4QixLQUFLLEdBQUcsRUFBRSxDQUFDO0lBQ1gsZ0JBQWdCLEdBQUcsS0FBSyxDQUFDO0lBQ3hCLFdBQVcsR0FBRyxJQUFJLFlBQVksRUFBYSxDQUFDLENBQUMsbUNBQW1DO0lBRTFGLFdBQVcsR0FBOEIsTUFBTSxDQUFDO0lBQ2hELFFBQVEsR0FBUyxJQUFJLElBQUksRUFBRSxDQUFDO0lBRTVCLGtCQUFrQjtJQUNsQixLQUFLLEdBQWMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUU5QyxRQUFRLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLElBQUks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SSxXQUFXO3NCQUFwQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT25Jbml0LCBmb3J3YXJkUmVmLCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7XG4gIGFkZE1vbnRocywgc3ViTW9udGhzLCBzdGFydE9mTW9udGgsIGVuZE9mTW9udGgsXG4gIHN0YXJ0T2ZXZWVrLCBlbmRPZldlZWssIGVhY2hEYXlPZkludGVydmFsLCBpc1NhbWVNb250aCxcbiAgaXNTYW1lRGF5LCBpc1RvZGF5LCBzZXRNb250aCwgc2V0WWVhciwgYWRkWWVhcnMsIHN1YlllYXJzLFxuICBpc0JlZm9yZSwgc3RhcnRPZkRheSwgaXNXaXRoaW5JbnRlcnZhbCwgaXNBZnRlclxufSBmcm9tICdkYXRlLWZucyc7XG5pbXBvcnQgeyBjbiB9IGZyb20gJy4vdXRpbHMvY24nO1xuaW1wb3J0IHtEYXRlUmFuZ2V9IGZyb20gJ0B0b2xsZS91aS90eXBlcy9kYXRlLXJhbmdlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndG9sbGUtcmFuZ2UtY2FsZW5kYXInLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBSYW5nZUNhbGVuZGFyQ29tcG9uZW50KSxcbiAgICAgIG11bHRpOiB0cnVlXG4gICAgfVxuICBdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgW2NsYXNzXT1cImNuKCdwLTMgYm9yZGVyIHJvdW5kZWQtbWQgYmctYmFja2dyb3VuZCB0ZXh0LXBvcG92ZXItZm9yZWdyb3VuZCBzaGFkb3ctc20gaW5saW5lLWJsb2NrIG1pbi13LWZpdCcsIGNsYXNzKVwiPlxuXG4gICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1iZXR3ZWVuIHB0LTEgcGItNCBnYXAtMlwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTFcIj5cbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwic2V0VmlldygnbW9udGgnKVwiXG4gICAgICAgICAgICBbY2xhc3NdPVwiY24oJ3RleHQtc20gZm9udC1zZW1pYm9sZCBweC0yIHB5LTEgcm91bmRlZCB0cmFuc2l0aW9uLWNvbG9ycycsIGN1cnJlbnRWaWV3ID09PSAnbW9udGgnID8gJ2JnLXNlY29uZGFyeSB0ZXh0LXNlY29uZGFyeS1mb3JlZ3JvdW5kJyA6ICdob3ZlcjpiZy1hY2NlbnQgaG92ZXI6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCcpXCI+XG4gICAgICAgICAgICB7eyB2aWV3RGF0ZSB8IGRhdGU6ICdNTU1NJyB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCJzZXRWaWV3KCd5ZWFyJylcIlxuICAgICAgICAgICAgW2NsYXNzXT1cImNuKCd0ZXh0LXNtIGZvbnQtc2VtaWJvbGQgcHgtMiBweS0xIHJvdW5kZWQgdHJhbnNpdGlvbi1jb2xvcnMnLCBjdXJyZW50VmlldyA9PT0gJ3llYXInID8gJ2JnLXNlY29uZGFyeSB0ZXh0LXNlY29uZGFyeS1mb3JlZ3JvdW5kJyA6ICdob3ZlcjpiZy1hY2NlbnQgaG92ZXI6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCcpXCI+XG4gICAgICAgICAgICB7eyB2aWV3RGF0ZSB8IGRhdGU6ICd5eXl5JyB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIHNwYWNlLXgtMVwiPlxuICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCJwcmV2KClcIiBbY2xhc3NdPVwibmF2QnRuQ2xhc3NcIj48aSBjbGFzcz1cInJpLWFycm93LWxlZnQtcy1saW5lIHRleHQtbGdcIj48L2k+PC9idXR0b24+XG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cIm5leHQoKVwiIFtjbGFzc109XCJuYXZCdG5DbGFzc1wiPjxpIGNsYXNzPVwicmktYXJyb3ctcmlnaHQtcy1saW5lIHRleHQtbGdcIj48L2k+PC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxkaXYgKm5nSWY9XCJjdXJyZW50VmlldyA9PT0gJ2RhdGUnXCIgY2xhc3M9XCJzcGFjZS15LTIgYW5pbWF0ZS1pbiBmYWRlLWluIHpvb20taW4tOTUgZHVyYXRpb24tMjAwXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJncmlkIGdyaWQtY29scy03IGdhcC15LTEgdy1mdWxsXCI+XG4gICAgICAgICAgPHNwYW4gKm5nRm9yPVwibGV0IGRheSBvZiB3ZWVrRGF5c1wiIGNsYXNzPVwidGV4dC1bMC44cmVtXSB0ZXh0LW11dGVkLWZvcmVncm91bmQgZm9udC1ub3JtYWwgdGV4dC1jZW50ZXIgdy05XCI+XG4gICAgICAgICAgICB7eyBkYXkgfX1cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZ3JpZCBncmlkLWNvbHMtNyBnYXAteS0xIHctZnVsbFwiPlxuICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICpuZ0Zvcj1cImxldCBkYXRlIG9mIGRheXNJbk1vbnRoXCJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdERhdGUoZGF0ZSlcIlxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cImlzRGF0ZURpc2FibGVkKGRhdGUpXCJcbiAgICAgICAgICAgIFtjbGFzc109XCJnZXREYXlDbGFzcyhkYXRlKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAge3sgZGF0ZSB8IGRhdGU6ICdkJyB9fVxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2ICpuZ0lmPVwiY3VycmVudFZpZXcgPT09ICdtb250aCdcIiBjbGFzcz1cImdyaWQgZ3JpZC1jb2xzLTMgZ2FwLTIgdy02NCBhbmltYXRlLWluIGZhZGUtaW4gem9vbS1pbi05NSBkdXJhdGlvbi0yMDBcIj5cbiAgICAgICAgPGJ1dHRvbiAqbmdGb3I9XCJsZXQgbW9udGggb2YgbW9udGhzOyBsZXQgaSA9IGluZGV4XCIgdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCJzZWxlY3RNb250aChpKVwiXG4gICAgICAgICAgW2NsYXNzXT1cImNuKCd0ZXh0LXNtIHB5LTIuNSByb3VuZGVkLW1kIGhvdmVyOmJnLWFjY2VudCBob3Zlcjp0ZXh0LWFjY2VudC1mb3JlZ3JvdW5kIHRyYW5zaXRpb24tY29sb3JzJywgaSA9PT0gdmlld0RhdGUuZ2V0TW9udGgoKSA/ICdiZy1wcmltYXJ5IHRleHQtcHJpbWFyeS1mb3JlZ3JvdW5kJyA6ICcnKVwiPlxuICAgICAgICAgIHt7IG1vbnRoIH19XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxkaXYgKm5nSWY9XCJjdXJyZW50VmlldyA9PT0gJ3llYXInXCIgY2xhc3M9XCJncmlkIGdyaWQtY29scy00IGdhcC0yIHctNjQgYW5pbWF0ZS1pbiBmYWRlLWluIHpvb20taW4tOTUgZHVyYXRpb24tMjAwXCI+XG4gICAgICAgIDxidXR0b24gKm5nRm9yPVwibGV0IHllYXIgb2YgeWVhcnNcIiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cInNlbGVjdFllYXIoeWVhcilcIlxuICAgICAgICAgIFtjbGFzc109XCJjbigndGV4dC1zbSBweS0yIHJvdW5kZWQtbWQgaG92ZXI6YmctYWNjZW50IGhvdmVyOnRleHQtYWNjZW50LWZvcmVncm91bmQgdHJhbnNpdGlvbi1jb2xvcnMnLCB5ZWFyID09PSB2aWV3RGF0ZS5nZXRGdWxsWWVhcigpID8gJ2JnLXByaW1hcnkgdGV4dC1wcmltYXJ5LWZvcmVncm91bmQnIDogJycpXCI+XG4gICAgICAgICAge3sgeWVhciB9fVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICBgXG59KVxuZXhwb3J0IGNsYXNzIFJhbmdlQ2FsZW5kYXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIENvbnRyb2xWYWx1ZUFjY2Vzc29yIHtcbiAgQElucHV0KCkgY2xhc3MgPSAnJztcbiAgQElucHV0KCkgZGlzYWJsZVBhc3REYXRlcyA9IGZhbHNlO1xuICBAT3V0cHV0KCkgcmFuZ2VTZWxlY3QgPSBuZXcgRXZlbnRFbWl0dGVyPERhdGVSYW5nZT4oKTsgLy8gRW1pdHMgd2hlbmV2ZXIgc2VsZWN0aW9uIGNoYW5nZXNcblxuICBjdXJyZW50VmlldzogJ2RhdGUnIHwgJ21vbnRoJyB8ICd5ZWFyJyA9ICdkYXRlJztcbiAgdmlld0RhdGU6IERhdGUgPSBuZXcgRGF0ZSgpO1xuXG4gIC8vIFRoZSBSYW5nZSBWYWx1ZVxuICB2YWx1ZTogRGF0ZVJhbmdlID0geyBzdGFydDogbnVsbCwgZW5kOiBudWxsIH07XG5cbiAgd2Vla0RheXMgPSBbJ1N1JywgJ01vJywgJ1R1JywgJ1dlJywgJ1RoJywgJ0ZyJywgJ1NhJ107XG4gIGRheXNJbk1vbnRoOiBEYXRlW10gPSBbXTtcbiAgbW9udGhzID0gWydKYW4nLCAnRmViJywgJ01hcicsICdBcHInLCAnTWF5JywgJ0p1bicsICdKdWwnLCAnQXVnJywgJ1NlcCcsICdPY3QnLCAnTm92JywgJ0RlYyddO1xuICB5ZWFyczogbnVtYmVyW10gPSBbXTtcblxuICBuYXZCdG5DbGFzcyA9IGNuKCdoLTcgdy03IGJnLXRyYW5zcGFyZW50IHAtMCBvcGFjaXR5LTUwIGhvdmVyOm9wYWNpdHktMTAwIGJvcmRlciBib3JkZXItaW5wdXQgcm91bmRlZC1tZCBmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBob3ZlcjpiZy1hY2NlbnQgaG92ZXI6dGV4dC1hY2NlbnQtZm9yZWdyb3VuZCB0cmFuc2l0aW9uLWFsbCcpO1xuXG4gIG9uVG91Y2hlZDogKCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuICBvbkNoYW5nZTogKHZhbHVlOiBEYXRlUmFuZ2UpID0+IHZvaWQgPSAoKSA9PiB7fTtcbiAgcHJvdGVjdGVkIGNuID0gY247XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5nZW5lcmF0ZURheXMoKTtcbiAgICB0aGlzLmdlbmVyYXRlWWVhcnMoKTtcbiAgfVxuXG4gIC8vIC0tLSBEYXRlIEdlbmVyYXRpb24gTG9naWMgKFNhbWUgYXMgQ2FsZW5kYXIpIC0tLVxuICBnZW5lcmF0ZURheXMoKSB7XG4gICAgY29uc3Qgc3RhcnQgPSBzdGFydE9mV2VlayhzdGFydE9mTW9udGgodGhpcy52aWV3RGF0ZSkpO1xuICAgIGNvbnN0IGVuZCA9IGVuZE9mV2VlayhlbmRPZk1vbnRoKHRoaXMudmlld0RhdGUpKTtcbiAgICB0aGlzLmRheXNJbk1vbnRoID0gZWFjaERheU9mSW50ZXJ2YWwoeyBzdGFydCwgZW5kIH0pO1xuICB9XG5cbiAgZ2VuZXJhdGVZZWFycygpIHtcbiAgICBjb25zdCBjdXJyZW50WWVhciA9IHRoaXMudmlld0RhdGUuZ2V0RnVsbFllYXIoKTtcbiAgICB0aGlzLnllYXJzID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogMTYgfSwgKF8sIGkpID0+IGN1cnJlbnRZZWFyIC0gNiArIGkpO1xuICB9XG5cbiAgc2V0Vmlldyh2aWV3OiAnZGF0ZScgfCAnbW9udGgnIHwgJ3llYXInKSB7XG4gICAgdGhpcy5jdXJyZW50VmlldyA9IHZpZXc7XG4gICAgaWYgKHZpZXcgPT09ICd5ZWFyJykgdGhpcy5nZW5lcmF0ZVllYXJzKCk7XG4gIH1cblxuICBwcmV2KCkge1xuICAgIGlmICh0aGlzLmN1cnJlbnRWaWV3ID09PSAnZGF0ZScpIHtcbiAgICAgIHRoaXMudmlld0RhdGUgPSBzdWJNb250aHModGhpcy52aWV3RGF0ZSwgMSk7XG4gICAgICB0aGlzLmdlbmVyYXRlRGF5cygpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5jdXJyZW50VmlldyA9PT0gJ3llYXInKSB7XG4gICAgICB0aGlzLnZpZXdEYXRlID0gc3ViWWVhcnModGhpcy52aWV3RGF0ZSwgMTYpO1xuICAgICAgdGhpcy5nZW5lcmF0ZVllYXJzKCk7XG4gICAgfSBlbHNlIGlmICh0aGlzLmN1cnJlbnRWaWV3ID09PSAnbW9udGgnKSB7XG4gICAgICB0aGlzLnZpZXdEYXRlID0gc3ViWWVhcnModGhpcy52aWV3RGF0ZSwgMSk7XG4gICAgfVxuICB9XG5cbiAgbmV4dCgpIHtcbiAgICBpZiAodGhpcy5jdXJyZW50VmlldyA9PT0gJ2RhdGUnKSB7XG4gICAgICB0aGlzLnZpZXdEYXRlID0gYWRkTW9udGhzKHRoaXMudmlld0RhdGUsIDEpO1xuICAgICAgdGhpcy5nZW5lcmF0ZURheXMoKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuY3VycmVudFZpZXcgPT09ICd5ZWFyJykge1xuICAgICAgdGhpcy52aWV3RGF0ZSA9IGFkZFllYXJzKHRoaXMudmlld0RhdGUsIDE2KTtcbiAgICAgIHRoaXMuZ2VuZXJhdGVZZWFycygpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5jdXJyZW50VmlldyA9PT0gJ21vbnRoJykge1xuICAgICAgdGhpcy52aWV3RGF0ZSA9IGFkZFllYXJzKHRoaXMudmlld0RhdGUsIDEpO1xuICAgIH1cbiAgfVxuXG4gIC8vIC0tLSBSYW5nZSBTZWxlY3Rpb24gTG9naWMgLS0tXG5cbiAgc2VsZWN0RGF0ZShkYXRlOiBEYXRlKSB7XG4gICAgaWYgKHRoaXMuaXNEYXRlRGlzYWJsZWQoZGF0ZSkpIHJldHVybjtcblxuICAgIGNvbnN0IHsgc3RhcnQsIGVuZCB9ID0gdGhpcy52YWx1ZTtcblxuICAgIC8vIDEuIElmIHN0YXJ0IGV4aXN0cyBidXQgZW5kIGRvZXNuJ3RcbiAgICBpZiAoc3RhcnQgJiYgIWVuZCkge1xuICAgICAgaWYgKGlzQmVmb3JlKGRhdGUsIHN0YXJ0KSkge1xuICAgICAgICAvLyBVc2VyIGNsaWNrZWQgZWFybGllciBkYXRlIC0+IFJlc2V0IHN0YXJ0XG4gICAgICAgIHRoaXMudmFsdWUgPSB7IHN0YXJ0OiBkYXRlLCBlbmQ6IG51bGwgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFVzZXIgY2xpY2tlZCBsYXRlciBkYXRlIC0+IENvbXBsZXRlIHJhbmdlXG4gICAgICAgIHRoaXMudmFsdWUgPSB7IHN0YXJ0LCBlbmQ6IGRhdGUgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gMi4gSWYgbmVpdGhlciBleGlzdCBPUiBib3RoIGV4aXN0IChyZXNldClcbiAgICBlbHNlIHtcbiAgICAgIHRoaXMudmFsdWUgPSB7IHN0YXJ0OiBkYXRlLCBlbmQ6IG51bGwgfTtcbiAgICB9XG5cbiAgICBpZiAoIWlzU2FtZU1vbnRoKGRhdGUsIHRoaXMudmlld0RhdGUpKSB7XG4gICAgICB0aGlzLnZpZXdEYXRlID0gZGF0ZTtcbiAgICAgIHRoaXMuZ2VuZXJhdGVEYXlzKCk7XG4gICAgfVxuXG4gICAgdGhpcy5vbkNoYW5nZSh0aGlzLnZhbHVlKTtcbiAgICB0aGlzLnJhbmdlU2VsZWN0LmVtaXQodGhpcy52YWx1ZSk7XG4gICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgfVxuXG4gIHNlbGVjdE1vbnRoKG1vbnRoSW5kZXg6IG51bWJlcikge1xuICAgIHRoaXMudmlld0RhdGUgPSBzZXRNb250aCh0aGlzLnZpZXdEYXRlLCBtb250aEluZGV4KTtcbiAgICB0aGlzLmN1cnJlbnRWaWV3ID0gJ2RhdGUnO1xuICAgIHRoaXMuZ2VuZXJhdGVEYXlzKCk7XG4gIH1cblxuICBzZWxlY3RZZWFyKHllYXI6IG51bWJlcikge1xuICAgIHRoaXMudmlld0RhdGUgPSBzZXRZZWFyKHRoaXMudmlld0RhdGUsIHllYXIpO1xuICAgIHRoaXMuY3VycmVudFZpZXcgPSAnZGF0ZSc7XG4gICAgdGhpcy5nZW5lcmF0ZURheXMoKTtcbiAgfVxuXG4gIC8vIC0tLSBWaXN1YWwgU3R5bGluZyBmb3IgUmFuZ2UgLS0tXG5cbiAgZ2V0RGF5Q2xhc3MoZGF0ZTogRGF0ZSkge1xuICAgIGNvbnN0IHsgc3RhcnQsIGVuZCB9ID0gdGhpcy52YWx1ZTtcbiAgICBjb25zdCBpc091dHNpZGUgPSAhaXNTYW1lTW9udGgoZGF0ZSwgdGhpcy52aWV3RGF0ZSk7XG4gICAgY29uc3QgaXNEaXNhYmxlZCA9IHRoaXMuaXNEYXRlRGlzYWJsZWQoZGF0ZSk7XG5cbiAgICAvLyBSYW5nZSBDaGVja3NcbiAgICBjb25zdCBpc1N0YXJ0ID0gc3RhcnQgJiYgaXNTYW1lRGF5KGRhdGUsIHN0YXJ0KTtcbiAgICBjb25zdCBpc0VuZCA9IGVuZCAmJiBpc1NhbWVEYXkoZGF0ZSwgZW5kKTtcbiAgICBjb25zdCBpc0luc2lkZSA9IHN0YXJ0ICYmIGVuZCAmJiBpc1dpdGhpbkludGVydmFsKGRhdGUsIHsgc3RhcnQsIGVuZCB9KTtcbiAgICBjb25zdCBpc1RvZGF5RGF0ZSA9IGlzVG9kYXkoZGF0ZSk7XG5cbiAgICByZXR1cm4gY24oXG4gICAgICAvLyBCYXNlOiBoLTkgdy05LCBidXQgd2UgcmVtb3ZlIG1hcmdpbnMvcm91bmRpbmcgZm9yIHRoZSAnc3RyaXAnIGVmZmVjdFxuICAgICAgJ2gtOSB3LTkgcC0wIGZvbnQtbm9ybWFsIHRleHQtc20gdHJhbnNpdGlvbi1hbGwgZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcmVsYXRpdmUgei0xMCcsXG5cbiAgICAgIC8vIERlZmF1bHQgU3RhdGUgKE5vdCBzZWxlY3RlZCwgTm90IGRpc2FibGVkKVxuICAgICAgIWlzSW5zaWRlICYmICFpc1N0YXJ0ICYmICFpc0VuZCAmJiAhaXNEaXNhYmxlZCAmJiAnaG92ZXI6YmctYWNjZW50IGhvdmVyOnRleHQtYWNjZW50LWZvcmVncm91bmQgcm91bmRlZC1tZCcsXG5cbiAgICAgIC8vIFRoZSBcIkNhcHNcIjogU3RhcnQgYW5kIEVuZFxuICAgICAgKGlzU3RhcnQgfHwgaXNFbmQpICYmICdiZy1wcmltYXJ5IHRleHQtcHJpbWFyeS1mb3JlZ3JvdW5kIGhvdmVyOmJnLXByaW1hcnkgaG92ZXI6dGV4dC1wcmltYXJ5LWZvcmVncm91bmQgZm9jdXM6YmctcHJpbWFyeSBmb2N1czp0ZXh0LXByaW1hcnktZm9yZWdyb3VuZCcsXG5cbiAgICAgIC8vIFRoZSBcIlN0cmlwXCI6IERhdGVzIGJldHdlZW4gc3RhcnQgYW5kIGVuZFxuICAgICAgaXNJbnNpZGUgJiYgIWlzU3RhcnQgJiYgIWlzRW5kICYmICdiZy1hY2NlbnQgdGV4dC1hY2NlbnQtZm9yZWdyb3VuZCByb3VuZGVkLW5vbmUnLFxuXG4gICAgICAvLyBDb25uZWN0aW5nIHRoZSBDYXBzIHRvIHRoZSBTdHJpcCAoUmVjdGFuZ3VsYXIgaW5zaWRlIGVkZ2VzKVxuICAgICAgaXNTdGFydCAmJiBlbmQgJiYgJ3JvdW5kZWQtbC1tZCByb3VuZGVkLXItbm9uZScsXG4gICAgICBpc0VuZCAmJiBzdGFydCAmJiAncm91bmRlZC1yLW1kIHJvdW5kZWQtbC1ub25lJyxcbiAgICAgIC8vIElmIG5vIGVuZCBkYXRlIHlldCwgU3RhcnQgc2hvdWxkIGJlIGZ1bGx5IHJvdW5kZWRcbiAgICAgIGlzU3RhcnQgJiYgIWVuZCAmJiAncm91bmRlZC1tZCcsXG5cbiAgICAgIC8vIE11dGVkL0Rpc2FibGVkIGxvZ2ljXG4gICAgICAhaXNJbnNpZGUgJiYgaXNUb2RheURhdGUgJiYgIWlzU3RhcnQgJiYgIWlzRW5kICYmICdiZy1hY2NlbnQvNTAgdGV4dC1hY2NlbnQtZm9yZWdyb3VuZCByb3VuZGVkLW1kJyxcbiAgICAgIChpc091dHNpZGUgfHwgaXNEaXNhYmxlZCkgJiYgJ3RleHQtbXV0ZWQtZm9yZWdyb3VuZCBvcGFjaXR5LTUwJyxcbiAgICAgIGlzRGlzYWJsZWQgJiYgJ2N1cnNvci1ub3QtYWxsb3dlZCdcbiAgICApO1xuICB9XG5cbiAgaXNEYXRlRGlzYWJsZWQoZGF0ZTogRGF0ZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmRpc2FibGVQYXN0RGF0ZXMgPyBpc0JlZm9yZShkYXRlLCBzdGFydE9mRGF5KG5ldyBEYXRlKCkpKSA6IGZhbHNlO1xuICB9XG5cbiAgLy8gLS0tIENWQSBJbXBsZW1lbnRhdGlvbiAtLS1cbiAgd3JpdGVWYWx1ZSh2YWw6IERhdGVSYW5nZSB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAodmFsKSB7XG4gICAgICB0aGlzLnZhbHVlID0gdmFsO1xuICAgICAgaWYgKHZhbC5zdGFydCkgdGhpcy52aWV3RGF0ZSA9IHZhbC5zdGFydDtcbiAgICAgIHRoaXMuZ2VuZXJhdGVEYXlzKCk7XG4gICAgICB0aGlzLmdlbmVyYXRlWWVhcnMoKTtcbiAgICB9XG4gIH1cbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogYW55KTogdm9pZCB7IHRoaXMub25DaGFuZ2UgPSBmbjsgfVxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogYW55KTogdm9pZCB7IHRoaXMub25Ub3VjaGVkID0gZm47IH1cbn1cbiJdfQ==
|