@wkly/datetime-picker 15.1.0 → 16.1.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.
@@ -1,1629 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { InjectionToken, EventEmitter, Directive, Component, Input, Output, LOCALE_ID, PLATFORM_ID, forwardRef, Inject, ViewChild, Injectable, HostListener, NgModule } from '@angular/core';
3
- import * as i1 from '@angular/common';
4
- import { isPlatformBrowser, getLocaleFirstDayOfWeek, DOCUMENT, CommonModule } from '@angular/common';
5
- import { NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
6
- import { floorMod, integer, createWeekGenerator, absoluteWeekOf, firstEpochDayOf } from '@wkly/core';
7
- import { normalizeDigits, WklyGregorianCalendarAdapter, resolveWeekOffset, error, validateSelection, decodeIso } from '@wkly/adapters';
8
- import { DEFAULT_OVERSCAN_WEEKS, WklyPickerInputsPropertyKeys, WklyPickerOutputsPropertyKeys, coerceBoolean, resolveWklyTranslation, validateDrafts, draftDayDifference, setDraftDayDifference, calendarMonthBounds, createWeekRows, INPUT_NAMES } from '@wkly/presentation';
9
- export * from '@wkly/presentation';
10
-
11
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8;
12
- const WKLY_CLOCK = new InjectionToken("WKLY_CLOCK", {
13
- providedIn: "root",
14
- factory: () => ({ now: () => new Date() }),
15
- });
16
- const WKLY_CONFIG = new InjectionToken("WKLY_CONFIG", { providedIn: "root", factory: () => ({}) });
17
- const WKLY_LOCALIZATION = new InjectionToken("WKLY_LOCALIZATION", { providedIn: "root", factory: () => ({}) });
18
- const WKLY_TRANSLATIONS = new InjectionToken("WKLY_TRANSLATIONS", { providedIn: "root", factory: () => ({}) });
19
- /** Shared public inputs/outputs inherited by the picker and both trigger directives. */
20
- // Inherited inputs need literal names in published decorator metadata.
21
- class WklyPickerInputs {
22
- constructor() {
23
- this[_a] = "datetime";
24
- this[_b] = null;
25
- this[_c] = "";
26
- this[_d] = null;
27
- this[_e] = {
28
- kind: "full-month",
29
- };
30
- this[_f] = "locale";
31
- this[_g] = false;
32
- this[_h] = 1;
33
- this[_j] = 1;
34
- this[_k] = null;
35
- this[_l] = null;
36
- this[_m] = null;
37
- this[_o] = null;
38
- this[_p] = null;
39
- this[_q] = false;
40
- this[_r] = false;
41
- this[_s] = false;
42
- this[_t] = "locale";
43
- this[_u] = null;
44
- this[_v] = 256;
45
- this[_w] = DEFAULT_OVERSCAN_WEEKS;
46
- this[_x] = null;
47
- this[_y] = null;
48
- this[_z] = null;
49
- this[_0] = true;
50
- this[_1] = [];
51
- this[_2] = null;
52
- this[_3] = new EventEmitter();
53
- this[_4] = new EventEmitter(true);
54
- this[_5] = new EventEmitter();
55
- this[_6] = new EventEmitter();
56
- this[_7] = new EventEmitter(true);
57
- this[_8] = new EventEmitter();
58
- }
59
- }
60
- _a = WklyPickerInputsPropertyKeys.Mode, _b = WklyPickerInputsPropertyKeys.Value, WklyPickerInputsPropertyKeys.CalendarAdapter, _c = WklyPickerInputsPropertyKeys.Locale, _d = WklyPickerInputsPropertyKeys.WeekOffset, _e = WklyPickerInputsPropertyKeys.ViewportPreset, _f = WklyPickerInputsPropertyKeys.HourCycle, _g = WklyPickerInputsPropertyKeys.ShowSeconds, _h = WklyPickerInputsPropertyKeys.MinuteStep, _j = WklyPickerInputsPropertyKeys.SecondStep, _k = WklyPickerInputsPropertyKeys.Min, _l = WklyPickerInputsPropertyKeys.Max, _m = WklyPickerInputsPropertyKeys.IsDateDisabled, _o = WklyPickerInputsPropertyKeys.IsTimeDisabled, _p = WklyPickerInputsPropertyKeys.RangeValidator, _q = WklyPickerInputsPropertyKeys.AllowRangeAcrossDisabled, _r = WklyPickerInputsPropertyKeys.Required, _s = WklyPickerInputsPropertyKeys.Disabled, _t = WklyPickerInputsPropertyKeys.WeekLabelMode, _u = WklyPickerInputsPropertyKeys.WeekLabelFormatter, _v = WklyPickerInputsPropertyKeys.WeekCacheSize, _w = WklyPickerInputsPropertyKeys.OverscanWeeks, _x = WklyPickerInputsPropertyKeys.AriaLabel, _y = WklyPickerInputsPropertyKeys.AriaDescribedBy, _z = WklyPickerInputsPropertyKeys.InitialEpochDay, _0 = WklyPickerInputsPropertyKeys.CloseOnBackdrop, _1 = WklyPickerInputsPropertyKeys.Validators, _2 = WklyPickerInputsPropertyKeys.Translations, _3 = WklyPickerOutputsPropertyKeys.ValueChange, _4 = WklyPickerOutputsPropertyKeys.ValidationChange, _5 = WklyPickerOutputsPropertyKeys.Opened, _6 = WklyPickerOutputsPropertyKeys.Closed, _7 = WklyPickerOutputsPropertyKeys.ViewportChange, _8 = WklyPickerOutputsPropertyKeys.ViewModeChange;
61
- WklyPickerInputs.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyPickerInputs, deps: [], target: i0.ɵɵFactoryTarget.Directive });
62
- WklyPickerInputs.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: WklyPickerInputs, inputs: { mode: "mode", value: "value", calendarAdapter: "calendarAdapter", locale: "locale", weekOffset: "weekOffset", viewportPreset: "viewportPreset", hourCycle: "hourCycle", showSeconds: "showSeconds", minuteStep: "minuteStep", secondStep: "secondStep", min: "min", max: "max", isDateDisabled: "isDateDisabled", isTimeDisabled: "isTimeDisabled", rangeValidator: "rangeValidator", allowRangeAcrossDisabled: "allowRangeAcrossDisabled", required: "required", disabled: "disabled", weekLabelMode: "weekLabelMode", weekLabelFormatter: "weekLabelFormatter", weekCacheSize: "weekCacheSize", overscanWeeks: "overscanWeeks", ariaLabel: "ariaLabel", ariaDescribedBy: "ariaDescribedBy", initialEpochDay: "initialEpochDay", closeOnBackdrop: "closeOnBackdrop", validators: "validators", translations: "translations" }, outputs: { valueChange: "valueChange", validationChange: "validationChange", opened: "opened", closed: "closed", viewportChange: "viewportChange", viewModeChange: "viewModeChange" }, ngImport: i0 });
63
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyPickerInputs, decorators: [{
64
- type: Directive,
65
- args: [{
66
- inputs: [
67
- "mode",
68
- "value",
69
- "calendarAdapter",
70
- "locale",
71
- "weekOffset",
72
- "viewportPreset",
73
- "hourCycle",
74
- "showSeconds",
75
- "minuteStep",
76
- "secondStep",
77
- "min",
78
- "max",
79
- "isDateDisabled",
80
- "isTimeDisabled",
81
- "rangeValidator",
82
- "allowRangeAcrossDisabled",
83
- "required",
84
- "disabled",
85
- "weekLabelMode",
86
- "weekLabelFormatter",
87
- "weekCacheSize",
88
- "overscanWeeks",
89
- "ariaLabel",
90
- "ariaDescribedBy",
91
- "initialEpochDay",
92
- "closeOnBackdrop",
93
- "validators",
94
- "translations",
95
- ],
96
- outputs: [
97
- "valueChange",
98
- "validationChange",
99
- "opened",
100
- "closed",
101
- "viewportChange",
102
- "viewModeChange",
103
- ],
104
- }]
105
- }] });
106
-
107
- class WklyFieldComponent {
108
- constructor() {
109
- this.value = 0;
110
- this.label = "";
111
- this.hideLabel = false;
112
- this.previousLabel = "";
113
- this.nextLabel = "";
114
- this.min = 0;
115
- this.max = 59;
116
- this.step = 1;
117
- this.locale = "en-US";
118
- this.disabled = false;
119
- this.invalid = false;
120
- this.labels = null;
121
- this.valueChange = new EventEmitter();
122
- this.complete = new EventEmitter();
123
- this.before = null;
124
- this.touchY = 0;
125
- this.touchSteps = 0;
126
- this.touchChanged = false;
127
- this.typed = null;
128
- this.inputTimer = null;
129
- this.wheelTimer = null;
130
- }
131
- get display() {
132
- if (this.typed !== null)
133
- return this.typed;
134
- return this.value === null
135
- ? ""
136
- : this.labels
137
- ? this.labels[this.value - this.min] || String(this.value)
138
- : new Intl.NumberFormat(this.locale, {
139
- useGrouping: false,
140
- minimumIntegerDigits: this.max < 60 ? 2 : 1,
141
- }).format(this.value);
142
- }
143
- ngOnChanges(changes) {
144
- if (changes.value && this.min < 0 && this.typed !== null) {
145
- const typedValue = this.typed === "" || this.typed === "-" ? null : Number(this.typed);
146
- if (this.value !== typedValue) {
147
- // External date edits replace a pending relative-day preview.
148
- this.cancelInput();
149
- this.typed = null;
150
- }
151
- }
152
- }
153
- ngOnDestroy() {
154
- this.cancelInput();
155
- if (this.wheelTimer !== null)
156
- clearTimeout(this.wheelTimer);
157
- }
158
- next(delta) {
159
- const count = Math.floor((this.max - this.min) / this.step) + 1;
160
- return (this.min +
161
- floorMod(Math.floor(((this.value === null ? this.min : this.value) - this.min) /
162
- this.step) + delta, count) *
163
- this.step);
164
- }
165
- neighbor(delta) {
166
- const n = this.next(delta);
167
- return this.labels
168
- ? this.labels[n - this.min] || ""
169
- : new Intl.NumberFormat(this.locale, { useGrouping: false }).format(n);
170
- }
171
- stepBy(delta) {
172
- if (this.disabled)
173
- return;
174
- this.scrollBy(delta);
175
- this.complete.emit();
176
- }
177
- begin(event) {
178
- this.before = this.value;
179
- event.target.select();
180
- }
181
- type(event) {
182
- if (this.disabled)
183
- return;
184
- const input = event.target;
185
- const raw = input.value;
186
- const numeric = Array.from(raw).every((character) => normalizeDigits(character).length === 1);
187
- if (this.min < 0 && !this.labels) {
188
- // Preserve the sign while using the same locale digit normalization.
189
- const signed = raw
190
- .replace(/[\u200e\u200f\u061c]/g, "")
191
- .replace(/\u2212/g, "-");
192
- const digits = normalizeDigits(signed);
193
- this.typed = input.value = (signed.startsWith("-") ? "-" : "") + digits;
194
- this.value =
195
- digits === ""
196
- ? null
197
- : Math.max(this.min, Math.min(this.max, Number(this.typed)));
198
- if (this.value !== null && Number(this.typed) !== this.value)
199
- this.typed = input.value = String(this.value);
200
- }
201
- else if (numeric) {
202
- const normalized = normalizeDigits(raw);
203
- this.typed = input.value =
204
- this.min >= 0 && this.max < 100 ? normalized.slice(-2) : normalized;
205
- this.value = this.typed === "" ? null : Number(this.typed);
206
- }
207
- else if (this.labels) {
208
- const search = raw.trim().toLocaleLowerCase(this.locale);
209
- this.typed = raw;
210
- const matches = this.labels
211
- .map((label, index) => ({ label, index }))
212
- .filter((item) => item.label.toLocaleLowerCase(this.locale).includes(search));
213
- this.value = matches.length === 1 ? this.min + matches[0].index : null;
214
- }
215
- else {
216
- this.typed = input.value = normalizeDigits(raw);
217
- this.value = this.typed === "" ? null : Number(this.typed);
218
- }
219
- this.valueChange.emit(this.value);
220
- this.cancelInput();
221
- if (!numeric && this.labels && this.value !== null)
222
- this.complete.emit();
223
- this.inputTimer = setTimeout(() => {
224
- this.inputTimer = null;
225
- this.typed = null;
226
- if (!this.disabled)
227
- this.complete.emit();
228
- }, 1000);
229
- }
230
- key(event) {
231
- if (event.key === "Escape") {
232
- event.preventDefault();
233
- event.stopPropagation();
234
- this.cancelInput();
235
- this.typed = null;
236
- this.value = this.before;
237
- this.valueChange.emit(this.before);
238
- event.target.value = this.display;
239
- event.target.blur();
240
- }
241
- if (event.key === "Enter") {
242
- event.preventDefault();
243
- event.stopPropagation();
244
- this.finish();
245
- }
246
- const delta = event.key === "ArrowUp"
247
- ? -1
248
- : event.key === "ArrowDown"
249
- ? 1
250
- : event.key === "PageUp"
251
- ? -5
252
- : event.key === "PageDown"
253
- ? 5
254
- : 0;
255
- if (delta) {
256
- event.preventDefault();
257
- this.stepBy(delta);
258
- }
259
- }
260
- finish() {
261
- this.cancelInput();
262
- this.typed = null;
263
- this.complete.emit();
264
- }
265
- wheel(event) {
266
- if (this.disabled || Math.abs(event.deltaY) < 1)
267
- return;
268
- event.preventDefault();
269
- this.scrollBy(event.deltaY > 0 ? 1 : -1);
270
- if (this.wheelTimer !== null)
271
- clearTimeout(this.wheelTimer);
272
- this.wheelTimer = setTimeout(() => {
273
- this.wheelTimer = null;
274
- this.complete.emit();
275
- }, 140);
276
- }
277
- touchStart(event) {
278
- this.touchY = event.touches[0].clientY;
279
- this.touchSteps = 0;
280
- this.touchChanged = false;
281
- }
282
- touchMove(event) {
283
- this.applyTouchY(event.touches[0].clientY);
284
- }
285
- touchEnd(event) {
286
- this.applyTouchY(event.changedTouches[0].clientY);
287
- if (this.touchChanged)
288
- this.complete.emit();
289
- this.touchChanged = false;
290
- }
291
- cancelInput() {
292
- if (this.inputTimer !== null)
293
- clearTimeout(this.inputTimer);
294
- this.inputTimer = null;
295
- }
296
- scrollBy(delta) {
297
- if (this.disabled || !delta)
298
- return;
299
- this.cancelInput();
300
- this.typed = null;
301
- this.value = this.next(delta);
302
- this.valueChange.emit(this.value);
303
- }
304
- applyTouchY(y) {
305
- // Count total gesture steps so repeated move events do not duplicate changes.
306
- if (this.disabled)
307
- return;
308
- const delta = this.touchY - y;
309
- const steps = Math.abs(delta) > 16
310
- ? Math.sign(delta) * Math.max(1, Math.round(Math.abs(delta) / 40))
311
- : 0;
312
- const change = steps - this.touchSteps;
313
- if (!change)
314
- return;
315
- this.scrollBy(change);
316
- this.touchSteps = steps;
317
- this.touchChanged = true;
318
- }
319
- }
320
- WklyFieldComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
321
- WklyFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WklyFieldComponent, selector: "wkly-field", inputs: { value: "value", label: "label", hideLabel: "hideLabel", previousLabel: "previousLabel", nextLabel: "nextLabel", min: "min", max: "max", step: "step", locale: "locale", disabled: "disabled", invalid: "invalid", labels: "labels" }, outputs: { valueChange: "valueChange", complete: "complete" }, usesOnChanges: true, ngImport: i0, template: "<div\n class=\"field\"\n (wheel)=\"wheel($event)\"\n (touchstart)=\"touchStart($event)\"\n (touchmove)=\"touchMove($event)\"\n (touchend)=\"touchEnd($event)\"\n (touchcancel)=\"touchEnd($event)\"\n>\n <span *ngIf=\"!hideLabel\" class=\"label\">{{ label }}</span>\n <button\n type=\"button\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"previousLabel || label + ': previous'\"\n (click)=\"stepBy(-1)\"\n >\n {{ neighbor(-1) }}\n </button>\n <input\n [attr.aria-label]=\"label\"\n [attr.aria-invalid]=\"invalid\"\n [disabled]=\"disabled\"\n [value]=\"display\"\n [attr.inputmode]=\"labels ? 'text' : min < 0 ? 'text' : 'numeric'\"\n autocomplete=\"off\"\n (focus)=\"begin($event)\"\n (input)=\"type($event)\"\n (blur)=\"finish()\"\n (keydown)=\"key($event)\"\n />\n <button\n type=\"button\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"nextLabel || label + ': next'\"\n (click)=\"stepBy(1)\"\n >\n {{ neighbor(1) }}\n </button>\n</div>\n", styles: [".field{display:flex;flex-direction:column;align-items:stretch;min-width:0;text-align:center;touch-action:pan-x}.label{font-size:11px;color:var(--wkly-muted-color, #54616e);margin-bottom:4px}button,input{font:inherit;box-sizing:border-box;min-height:44px;width:100%;border:0;text-align:center;background:transparent;color:inherit;border-radius:7px}button{color:var(--wkly-muted-color, #54616e);cursor:pointer}input{font-size:18px;font-weight:650;background:var(--wkly-range-color, #e5f1ee);border-block:2px solid var(--wkly-accent-color, #176c55)}input[aria-invalid=true]{border-color:var(--wkly-error-color, #b42318)}:focus-visible{outline:2px solid var(--wkly-focus-color, #124ee0);outline-offset:1px}button:disabled,input:disabled{opacity:.45}@media (hover: hover) and (pointer: fine){button:hover:not(:disabled){background:var(--wkly-range-color, #e5f1ee)}}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
322
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyFieldComponent, decorators: [{
323
- type: Component,
324
- args: [{ selector: "wkly-field", template: "<div\n class=\"field\"\n (wheel)=\"wheel($event)\"\n (touchstart)=\"touchStart($event)\"\n (touchmove)=\"touchMove($event)\"\n (touchend)=\"touchEnd($event)\"\n (touchcancel)=\"touchEnd($event)\"\n>\n <span *ngIf=\"!hideLabel\" class=\"label\">{{ label }}</span>\n <button\n type=\"button\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"previousLabel || label + ': previous'\"\n (click)=\"stepBy(-1)\"\n >\n {{ neighbor(-1) }}\n </button>\n <input\n [attr.aria-label]=\"label\"\n [attr.aria-invalid]=\"invalid\"\n [disabled]=\"disabled\"\n [value]=\"display\"\n [attr.inputmode]=\"labels ? 'text' : min < 0 ? 'text' : 'numeric'\"\n autocomplete=\"off\"\n (focus)=\"begin($event)\"\n (input)=\"type($event)\"\n (blur)=\"finish()\"\n (keydown)=\"key($event)\"\n />\n <button\n type=\"button\"\n [disabled]=\"disabled\"\n [attr.aria-label]=\"nextLabel || label + ': next'\"\n (click)=\"stepBy(1)\"\n >\n {{ neighbor(1) }}\n </button>\n</div>\n", styles: [".field{display:flex;flex-direction:column;align-items:stretch;min-width:0;text-align:center;touch-action:pan-x}.label{font-size:11px;color:var(--wkly-muted-color, #54616e);margin-bottom:4px}button,input{font:inherit;box-sizing:border-box;min-height:44px;width:100%;border:0;text-align:center;background:transparent;color:inherit;border-radius:7px}button{color:var(--wkly-muted-color, #54616e);cursor:pointer}input{font-size:18px;font-weight:650;background:var(--wkly-range-color, #e5f1ee);border-block:2px solid var(--wkly-accent-color, #176c55)}input[aria-invalid=true]{border-color:var(--wkly-error-color, #b42318)}:focus-visible{outline:2px solid var(--wkly-focus-color, #124ee0);outline-offset:1px}button:disabled,input:disabled{opacity:.45}@media (hover: hover) and (pointer: fine){button:hover:not(:disabled){background:var(--wkly-range-color, #e5f1ee)}}\n"] }]
325
- }], propDecorators: { value: [{
326
- type: Input
327
- }], label: [{
328
- type: Input
329
- }], hideLabel: [{
330
- type: Input
331
- }], previousLabel: [{
332
- type: Input
333
- }], nextLabel: [{
334
- type: Input
335
- }], min: [{
336
- type: Input
337
- }], max: [{
338
- type: Input
339
- }], step: [{
340
- type: Input
341
- }], locale: [{
342
- type: Input
343
- }], disabled: [{
344
- type: Input
345
- }], invalid: [{
346
- type: Input
347
- }], labels: [{
348
- type: Input
349
- }], valueChange: [{
350
- type: Output
351
- }], complete: [{
352
- type: Output
353
- }] } });
354
-
355
- class WklyDateTimePickerComponent extends WklyPickerInputs {
356
- constructor(defaultLocale, defaults, clock, strings, defaultTranslations, platform, host, changeDetector) {
357
- super();
358
- this.defaultLocale = defaultLocale;
359
- this.defaults = defaults;
360
- this.clock = clock;
361
- this.strings = strings;
362
- this.defaultTranslations = defaultTranslations;
363
- this.host = host;
364
- this.changeDetector = changeDetector;
365
- this.presentation = "inline";
366
- this.viewMode = "calendar";
367
- this.endView = "date";
368
- this.effectiveLocale = "en-US";
369
- this.effectiveOffset = 0;
370
- this.effectiveHourCycle = "h24";
371
- this.direction = "ltr";
372
- this.rows = [];
373
- this.weekdays = [];
374
- this.drafts = [];
375
- this.errors = [];
376
- this.today = 0;
377
- this.focused = 0;
378
- this.anchorWeek = 0;
379
- this.firstWeek = 0;
380
- this.visibleCount = 6;
381
- this.rowHeight = 76;
382
- this.scrollHeight = 152076;
383
- this.paddingTop = 0;
384
- this.initialized = false;
385
- this.compact = false;
386
- this.WklyPickerInputsPropertyKeys = WklyPickerInputsPropertyKeys;
387
- this.baseWeek = 0;
388
- this.firstSupportedDay = 0;
389
- this.lastSupportedDay = 0;
390
- this.firstSupportedWeek = 0;
391
- this.lastSupportedWeek = 0;
392
- this.initialMonth = "";
393
- this.clipMonth = false;
394
- this.browser = false;
395
- this.destroyed = false;
396
- this.snapPending = false;
397
- this.onChange = () => { };
398
- this.onTouched = () => { };
399
- this.validatorChanged = () => { };
400
- this.configErrors = [];
401
- this.pendingValue = null;
402
- this.emittedValue = null;
403
- this.manualDateEndpoint = 0;
404
- this.browser = isPlatformBrowser(platform);
405
- }
406
- ngOnInit() {
407
- this.initialize();
408
- }
409
- ngOnChanges(changes) {
410
- if (this.initialized) {
411
- if (Object.keys(changes).length === 1 &&
412
- changes[WklyPickerInputsPropertyKeys.Value] &&
413
- this.emittedValue ===
414
- JSON.stringify(this[WklyPickerInputsPropertyKeys.Value])) {
415
- this.emittedValue = null;
416
- return;
417
- }
418
- const focus = this.focused;
419
- this.configure();
420
- if (changes[WklyPickerInputsPropertyKeys.Value] ||
421
- changes[WklyPickerInputsPropertyKeys.Mode] ||
422
- changes[WklyPickerInputsPropertyKeys.CalendarAdapter]) {
423
- this.load(this[WklyPickerInputsPropertyKeys.Value]);
424
- this.position(this.focused, true);
425
- }
426
- else {
427
- this.check();
428
- if (changes[WklyPickerInputsPropertyKeys.ViewportPreset])
429
- this.position(focus, true);
430
- else
431
- this.scrollToEpochDay(focus);
432
- }
433
- }
434
- }
435
- initialize() {
436
- if (this.initialized)
437
- return;
438
- this.configure();
439
- const initialEpochDay = this[WklyPickerInputsPropertyKeys.InitialEpochDay];
440
- this.today = this.browser
441
- ? Math.floor(this.clock.now().getTime() / 86400000)
442
- : initialEpochDay === null
443
- ? 0
444
- : initialEpochDay;
445
- this.focused =
446
- initialEpochDay === null
447
- ? this.defaults.initialEpochDay === undefined
448
- ? this.today
449
- : this.defaults.initialEpochDay
450
- : initialEpochDay;
451
- this.load(this[WklyPickerInputsPropertyKeys.Value]);
452
- this.initialized = true;
453
- this.position(this.focused, true);
454
- }
455
- configure() {
456
- this.configErrors = [];
457
- [
458
- WklyPickerInputsPropertyKeys.ShowSeconds,
459
- WklyPickerInputsPropertyKeys.AllowRangeAcrossDisabled,
460
- WklyPickerInputsPropertyKeys.Required,
461
- WklyPickerInputsPropertyKeys.Disabled,
462
- WklyPickerInputsPropertyKeys.CloseOnBackdrop,
463
- ].forEach((key) => (this[key] = coerceBoolean(this[key])));
464
- this.effectiveLocale =
465
- this[WklyPickerInputsPropertyKeys.Locale] ||
466
- this.defaults.locale ||
467
- this.defaultLocale;
468
- this.direction = /^(ar|he|fa|ur)(-|$)/.test(this.effectiveLocale)
469
- ? "rtl"
470
- : "ltr";
471
- this.adapter =
472
- this[WklyPickerInputsPropertyKeys.CalendarAdapter] ||
473
- new WklyGregorianCalendarAdapter(this.effectiveLocale);
474
- try {
475
- let firstDay;
476
- try {
477
- firstDay = getLocaleFirstDayOfWeek(this.effectiveLocale);
478
- }
479
- catch (_) { }
480
- this.effectiveOffset = resolveWeekOffset(this.effectiveLocale, this[WklyPickerInputsPropertyKeys.WeekOffset], this.defaults.weekOffset, firstDay);
481
- integer(this[WklyPickerInputsPropertyKeys.WeekCacheSize]);
482
- integer(this[WklyPickerInputsPropertyKeys.OverscanWeeks]);
483
- if (this[WklyPickerInputsPropertyKeys.WeekCacheSize] < 0 ||
484
- this[WklyPickerInputsPropertyKeys.OverscanWeeks] < 0 ||
485
- this[WklyPickerInputsPropertyKeys.OverscanWeeks] > 50)
486
- throw new RangeError();
487
- if (![
488
- "datetime",
489
- "date",
490
- "time",
491
- "datetime-range",
492
- "date-range",
493
- "time-range",
494
- ].includes(this[WklyPickerInputsPropertyKeys.Mode]))
495
- throw new RangeError();
496
- const preset = this[WklyPickerInputsPropertyKeys.ViewportPreset];
497
- if (preset.kind === "weeks") {
498
- integer(preset.visibleWeekCount);
499
- if (preset.visibleWeekCount < 1 || preset.visibleWeekCount > 52)
500
- throw new RangeError();
501
- }
502
- if (preset.kind === "full-month-and-around")
503
- for (const n of [
504
- preset.extraWeeksBefore || 0,
505
- preset.extraWeeksAfter || 0,
506
- ]) {
507
- integer(n);
508
- if (n < 0 || n > 52)
509
- throw new RangeError();
510
- }
511
- this.generator = createWeekGenerator({
512
- weekOffset: this.effectiveOffset,
513
- cacheSize: this[WklyPickerInputsPropertyKeys.WeekCacheSize],
514
- });
515
- }
516
- catch (_) {
517
- this.configErrors.push(error("configuration-error", this[WklyPickerInputsPropertyKeys.WeekOffset]));
518
- this.generator = createWeekGenerator();
519
- this.effectiveOffset = 0;
520
- }
521
- this.setSupportedScrollRange();
522
- const hourCycle = this[WklyPickerInputsPropertyKeys.HourCycle];
523
- // Host value/configuration feedback must retain the user's switchable format.
524
- if (hourCycle !== "switchable" || this.configuredHourCycle !== hourCycle) {
525
- this.effectiveHourCycle =
526
- hourCycle === "h12"
527
- ? "h12"
528
- : hourCycle === "locale"
529
- ? new Intl.DateTimeFormat(this.effectiveLocale, {
530
- hour: "numeric",
531
- timeZone: "UTC",
532
- }).resolvedOptions().hour12
533
- ? "h12"
534
- : "h24"
535
- : "h24";
536
- }
537
- this.configuredHourCycle = hourCycle;
538
- this.weekdays = Array.from({ length: 7 }, (_, i) => this.adapter.formatWeekday(this.effectiveOffset + i, "short"));
539
- }
540
- setSupportedScrollRange() {
541
- let [first, last] = this.adapter.supportedEpochDayRange;
542
- const [firstYear, lastYear] = this.adapter.supportedYearRange;
543
- const yearOf = (day) => this.adapter.epochDayToDate(day).year;
544
- if (yearOf(first) < firstYear) {
545
- let low = first, high = last;
546
- while (low < high) {
547
- const mid = Math.floor((low + high) / 2);
548
- if (yearOf(mid) < firstYear)
549
- low = mid + 1;
550
- else
551
- high = mid;
552
- }
553
- first = low;
554
- }
555
- if (yearOf(last) > lastYear) {
556
- let low = first, high = last;
557
- while (low < high) {
558
- const mid = Math.ceil((low + high) / 2);
559
- if (yearOf(mid) > lastYear)
560
- high = mid - 1;
561
- else
562
- low = mid;
563
- }
564
- last = low;
565
- }
566
- if (first > last ||
567
- yearOf(first) < firstYear ||
568
- yearOf(first) > lastYear ||
569
- yearOf(last) < firstYear ||
570
- yearOf(last) > lastYear)
571
- throw new RangeError("No supported days within the calendar year range");
572
- this.firstSupportedDay = first;
573
- this.lastSupportedDay = last;
574
- this.firstSupportedWeek = absoluteWeekOf(first, this.effectiveOffset);
575
- this.lastSupportedWeek = absoluteWeekOf(last, this.effectiveOffset);
576
- }
577
- clampFirstWeek(week) {
578
- // Keep supported weeks inside the viewport; renderRows adds the buffer rows.
579
- const last = Math.max(this.firstSupportedWeek, this.lastSupportedWeek - this.visibleCount + 1);
580
- return Math.max(this.firstSupportedWeek, Math.min(last, week));
581
- }
582
- ngAfterViewInit() {
583
- this.resetScroll();
584
- if (this.browser && typeof ResizeObserver !== "undefined") {
585
- this.observer = new ResizeObserver(() => {
586
- this.compact = this.host.nativeElement.clientWidth < 338;
587
- const row = this.host.nativeElement.querySelector(".week-row");
588
- // CSS heights and scrollTop use layout pixels; client rectangles include zoom.
589
- const height = row ? parseFloat(getComputedStyle(row).height) : 0;
590
- if (height && height !== this.rowHeight) {
591
- this.rowHeight = height;
592
- this.scrollHeight = this.rowHeight * 2001;
593
- this.renderRows();
594
- this.resetScroll();
595
- }
596
- });
597
- this.observer.observe(this.host.nativeElement);
598
- }
599
- }
600
- ngOnDestroy() {
601
- this.destroyed = true;
602
- if (this.observer)
603
- this.observer.disconnect();
604
- if (this.scrollEndTimer)
605
- clearTimeout(this.scrollEndTimer);
606
- if (this.generator)
607
- this.generator.clearCache();
608
- }
609
- t(key) {
610
- return resolveWklyTranslation(key, this.effectiveLocale, this[WklyPickerInputsPropertyKeys.Translations] ||
611
- this.defaultTranslations, this.strings);
612
- }
613
- get isRange() {
614
- return this[WklyPickerInputsPropertyKeys.Mode].endsWith("-range");
615
- }
616
- get hasDate() {
617
- return !this[WklyPickerInputsPropertyKeys.Mode].startsWith("time");
618
- }
619
- get hasTime() {
620
- return (this[WklyPickerInputsPropertyKeys.Mode] !== "date" &&
621
- this[WklyPickerInputsPropertyKeys.Mode] !== "date-range");
622
- }
623
- get submitVisible() {
624
- return (this.presentation === "transient" &&
625
- (this[WklyPickerInputsPropertyKeys.Mode] !== "date" ||
626
- this.viewMode === "manual"));
627
- }
628
- get title() {
629
- try {
630
- const d = this.adapter.epochDayToDate(Math.max(this.firstSupportedDay, Math.min(this.lastSupportedDay, firstEpochDayOf(this.anchorWeek, this.effectiveOffset))));
631
- return this.adapter.formatMonth(d) + " " + this.adapter.formatYear(d);
632
- }
633
- catch (_) {
634
- return "";
635
- }
636
- }
637
- get canSubmit() {
638
- return (!this[WklyPickerInputsPropertyKeys.Disabled] &&
639
- !this.errors.length &&
640
- this.pendingValue !== null);
641
- }
642
- blank(day) {
643
- const safe = Math.max(this.firstSupportedDay, Math.min(this.lastSupportedDay, day));
644
- return {
645
- date: this.adapter.epochDayToDate(safe),
646
- hour: 0,
647
- minute: 0,
648
- second: 0,
649
- present: false,
650
- };
651
- }
652
- load(value) {
653
- this.drafts = [this.blank(this.focused), this.blank(this.focused)];
654
- const validation = validateSelection(value, this, this.adapter);
655
- if (value !== null && !validation.length) {
656
- const values = typeof value === "string" ? [value] : value;
657
- values.forEach((v, i) => {
658
- const d = decodeIso(v);
659
- this.drafts[i] = {
660
- date: this.hasDate
661
- ? this.adapter.epochDayToDate(d.epochDay)
662
- : this.blank(this.today).date,
663
- hour: d.hour,
664
- minute: d.minute,
665
- second: d.second,
666
- present: true,
667
- };
668
- if (i === 0 && this.hasDate)
669
- this.focused = d.epochDay;
670
- });
671
- }
672
- if (validation.length) {
673
- this.pendingValue = null;
674
- this.report(validation);
675
- }
676
- else
677
- this.check();
678
- }
679
- writeValue(value) {
680
- this[WklyPickerInputsPropertyKeys.Value] = value;
681
- if (this.initialized) {
682
- this.load(value);
683
- this.position(this.focused, true);
684
- }
685
- }
686
- registerOnChange(fn) {
687
- this.onChange = fn;
688
- }
689
- registerOnTouched(fn) {
690
- this.onTouched = fn;
691
- }
692
- setDisabledState(disabled) {
693
- this[WklyPickerInputsPropertyKeys.Disabled] = disabled;
694
- }
695
- validate(_control) {
696
- return this.errors.length ? { wkly: this.errors } : null;
697
- }
698
- registerOnValidatorChange(fn) {
699
- this.validatorChanged = fn;
700
- }
701
- touched() {
702
- Promise.resolve().then(() => this.onTouched());
703
- }
704
- report(errors) {
705
- const changed = JSON.stringify(this.errors) !== JSON.stringify(errors);
706
- this.errors = errors;
707
- if (changed) {
708
- this[WklyPickerOutputsPropertyKeys.ValidationChange].emit(errors);
709
- this.validatorChanged();
710
- }
711
- }
712
- check() {
713
- const result = validateDrafts({
714
- drafts: this.drafts,
715
- configErrors: this.configErrors,
716
- adapter: this.adapter,
717
- selection: this,
718
- mode: this[WklyPickerInputsPropertyKeys.Mode],
719
- isRange: this.isRange,
720
- hasDate: this.hasDate,
721
- hasTime: this.hasTime,
722
- showSeconds: this[WklyPickerInputsPropertyKeys.ShowSeconds],
723
- required: this[WklyPickerInputsPropertyKeys.Required],
724
- });
725
- this.pendingValue = result.pendingValue;
726
- this.report(result.errors);
727
- }
728
- trackDraft(index) {
729
- // Endpoint controls keep their identity and focus when draft objects swap.
730
- return index;
731
- }
732
- orderDrafts() {
733
- if (!this.isRange || !this.drafts.every((draft) => draft.present))
734
- return;
735
- if (this.drafts.some((draft) => draft.unsupportedEpochDay !== undefined))
736
- return;
737
- try {
738
- const a = this.drafts[0], b = this.drafts[1];
739
- const key = (d) => this.adapter.dateToEpochDay(d.date) * 86400 +
740
- (d.hour || 0) * 3600 +
741
- (d.minute || 0) * 60 +
742
- (d.second || 0);
743
- if (key(a) > key(b))
744
- this.drafts = [b, a];
745
- }
746
- catch (_) {
747
- // Impossible or incomplete dates remain editable until corrected.
748
- }
749
- }
750
- finish() {
751
- if (this[WklyPickerInputsPropertyKeys.Disabled])
752
- return;
753
- this.orderDrafts();
754
- if (this.viewMode === "manual" && this.hasDate)
755
- this.positionOnManualDate();
756
- this.check();
757
- if (this.presentation === "inline" && this.canSubmit)
758
- this.commit();
759
- }
760
- commit() {
761
- if (!this.canSubmit)
762
- return;
763
- const next = this.pendingValue;
764
- if (JSON.stringify(next) !==
765
- JSON.stringify(this[WklyPickerInputsPropertyKeys.Value])) {
766
- this[WklyPickerInputsPropertyKeys.Value] = next;
767
- this.emittedValue = JSON.stringify(next);
768
- this.onChange(next);
769
- this[WklyPickerOutputsPropertyKeys.ValueChange].emit(next);
770
- }
771
- this.onTouched();
772
- }
773
- submit(reason = "submit") {
774
- this.check();
775
- if (!this.canSubmit)
776
- return;
777
- this.commit();
778
- if (this.presentation === "transient")
779
- this[WklyPickerOutputsPropertyKeys.Closed].emit(reason);
780
- }
781
- cancel(reason = "close-button") {
782
- if (this[WklyPickerInputsPropertyKeys.Disabled])
783
- return;
784
- this.load(this[WklyPickerInputsPropertyKeys.Value]);
785
- this.onTouched();
786
- this[WklyPickerOutputsPropertyKeys.Closed].emit(reason);
787
- }
788
- now() {
789
- if (this[WklyPickerInputsPropertyKeys.Disabled])
790
- return;
791
- const n = this.clock.now();
792
- const day = Math.floor(n.getTime() / 86400000);
793
- this.drafts = [0, 1].map((index) => (Object.assign(Object.assign({}, this.clockDraft(day, n)), { present: index === 0 || this.isRange })));
794
- if (this.hasDate &&
795
- (day < this.firstSupportedDay || day > this.lastSupportedDay)) {
796
- this.report([error("unsupported-adapter-date", day)]);
797
- return;
798
- }
799
- this.focused = day;
800
- this.position(day, true);
801
- this.check();
802
- this.submit("now");
803
- }
804
- clockDraft(day, now) {
805
- return Object.assign(Object.assign({}, this.blank(day)), { hour: now.getUTCHours(), minute: Math.floor(now.getUTCMinutes() / this[WklyPickerInputsPropertyKeys.MinuteStep]) * this[WklyPickerInputsPropertyKeys.MinuteStep], second: this[WklyPickerInputsPropertyKeys.ShowSeconds]
806
- ? Math.floor(now.getUTCSeconds() / this[WklyPickerInputsPropertyKeys.SecondStep]) * this[WklyPickerInputsPropertyKeys.SecondStep]
807
- : 0 });
808
- }
809
- initializeManualRange() {
810
- if (!this.isRange ||
811
- !this.hasDate ||
812
- this.drafts.every((draft) => draft.present))
813
- return;
814
- let seed = this.drafts.find((draft) => draft.present);
815
- if (!seed) {
816
- if (this[WklyPickerInputsPropertyKeys.Value] !== null)
817
- return;
818
- const now = this.clock.now();
819
- const initialEpochDay = this[WklyPickerInputsPropertyKeys.InitialEpochDay];
820
- const day = initialEpochDay === null
821
- ? this.defaults.initialEpochDay === undefined
822
- ? Math.floor(now.getTime() / 86400000)
823
- : this.defaults.initialEpochDay
824
- : initialEpochDay;
825
- seed = Object.assign(Object.assign({}, this.clockDraft(day, now)), { present: true });
826
- }
827
- // Complete missing endpoints without replacing selected or invalid drafts.
828
- const initial = seed;
829
- this.drafts = this.drafts.map((draft) => draft.present ? draft : Object.assign(Object.assign({}, initial), { date: Object.assign({}, initial.date) }));
830
- this.finish();
831
- // Positioning renders before validation; refresh completion controls afterward.
832
- this.changeDetector.markForCheck();
833
- }
834
- toggleView() {
835
- if (this[WklyPickerInputsPropertyKeys.Disabled] || !this.hasDate)
836
- return;
837
- this.viewMode = this.viewMode === "calendar" ? "manual" : "calendar";
838
- if (this.viewMode === "manual")
839
- this.initializeManualRange();
840
- if (this.viewMode === "calendar")
841
- this.positionOnManualDate();
842
- this[WklyPickerOutputsPropertyKeys.ViewModeChange].emit(this.viewMode);
843
- if (this.viewMode === "calendar")
844
- setTimeout(() => this.resetScroll());
845
- }
846
- positionOnManualDate() {
847
- const draft = this.drafts[this.manualDateEndpoint];
848
- if (!draft || !draft.present)
849
- return;
850
- try {
851
- // A valid day follows the selection. An impossible day keeps its draft
852
- // fields but still shows the chosen month in the calendar.
853
- const target = this.adapter.dateToEpochDay(draft.date);
854
- this.focused = target;
855
- this.position(target, true);
856
- }
857
- catch (_) {
858
- try {
859
- const first = this.adapter.dateToEpochDay(Object.assign(Object.assign({}, draft.date), { day: 1 }));
860
- this.focused = first;
861
- this.position(first, true);
862
- }
863
- catch (_) { }
864
- }
865
- }
866
- months(draft) {
867
- try {
868
- return this.adapter.getMonths(draft.date.year).map((m) => m.label);
869
- }
870
- catch (_) {
871
- return [];
872
- }
873
- }
874
- monthCount(draft) {
875
- return this.months(draft).length || 12;
876
- }
877
- get inDays() {
878
- return draftDayDifference(this.drafts, this.adapter);
879
- }
880
- get inDaysLabel() {
881
- const days = this.inDays;
882
- return this.t("inDays").replace(/{{\s*days\s*}}/g, days === null
883
- ? this.t("daysUnavailable")
884
- : new Intl.NumberFormat(this.effectiveLocale, {
885
- useGrouping: false,
886
- }).format(days));
887
- }
888
- get resultingEndDate() {
889
- try {
890
- const draft = this.drafts[1];
891
- if (draft.unsupportedEpochDay !== undefined ||
892
- this.adapter.validateDate(draft.date).length)
893
- return "";
894
- return [
895
- this.adapter.formatDay(draft.date),
896
- this.adapter.formatMonth(draft.date),
897
- this.adapter.formatYear(draft.date),
898
- ].join(" ");
899
- }
900
- catch (_) {
901
- return "";
902
- }
903
- }
904
- toggleEndView(view) {
905
- if (this[WklyPickerInputsPropertyKeys.Disabled])
906
- return;
907
- this.endView = view;
908
- }
909
- days(value) {
910
- if (this[WklyPickerInputsPropertyKeys.Disabled])
911
- return;
912
- this.manualDateEndpoint = 1;
913
- setDraftDayDifference(this.drafts, this.adapter, value);
914
- this.check();
915
- }
916
- field(index, field, value) {
917
- if (this[WklyPickerInputsPropertyKeys.Disabled])
918
- return;
919
- const draft = this.drafts[index];
920
- draft.present = true;
921
- if (field === "day" || field === "year" || field === "month") {
922
- this.manualDateEndpoint = index;
923
- delete draft.unsupportedEpochDay;
924
- let date = Object.assign(Object.assign({}, draft.date), { [field]: value });
925
- if (field === "month") {
926
- let month;
927
- try {
928
- month = this.adapter
929
- .getMonths(date.year)
930
- .find((m) => m.month === value);
931
- }
932
- catch (_) { }
933
- date = Object.assign(Object.assign({}, date), { monthCode: month ? month.monthCode : "" });
934
- }
935
- if (field === "year" && value !== null) {
936
- try {
937
- const months = this.adapter.getMonths(value);
938
- const month = months.find((m) => m.monthCode === date.monthCode);
939
- if (month)
940
- date = Object.assign(Object.assign({}, date), { month: month.month });
941
- }
942
- catch (_) { }
943
- }
944
- draft.date = date;
945
- }
946
- else if (field === "hour" && this.effectiveHourCycle === "h12")
947
- draft.hour =
948
- value === null
949
- ? null
950
- : value >= 1 && value <= 12
951
- ? (value % 12) + ((draft.hour || 0) >= 12 ? 12 : 0)
952
- : 24 + value;
953
- else
954
- draft[field] = value;
955
- this.check();
956
- }
957
- displayHour(draft) {
958
- return draft.hour === null
959
- ? null
960
- : this.effectiveHourCycle === "h12"
961
- ? draft.hour % 12 || 12
962
- : draft.hour;
963
- }
964
- period(index, period) {
965
- if (this[WklyPickerInputsPropertyKeys.Disabled])
966
- return;
967
- if (period === "24")
968
- this.effectiveHourCycle = "h24";
969
- else {
970
- this.effectiveHourCycle = "h12";
971
- this.drafts[index].hour =
972
- ((this.drafts[index].hour || 0) % 12) + (period === "pm" ? 12 : 0);
973
- this.drafts[index].present = true;
974
- this.finish();
975
- }
976
- }
977
- selected(day) {
978
- return this.drafts.some((d) => {
979
- try {
980
- return d.present && this.adapter.dateToEpochDay(d.date) === day;
981
- }
982
- catch (_) {
983
- return false;
984
- }
985
- });
986
- }
987
- inRange(day) {
988
- if (!this.isRange || !this.drafts.every((d) => d.present))
989
- return false;
990
- try {
991
- const a = this.adapter.dateToEpochDay(this.drafts[0].date), b = this.adapter.dateToEpochDay(this.drafts[1].date);
992
- return day > Math.min(a, b) && day < Math.max(a, b);
993
- }
994
- catch (_) {
995
- return false;
996
- }
997
- }
998
- dayDisabled(day) {
999
- var _a, _b;
1000
- if (day < this.firstSupportedDay || day > this.lastSupportedDay)
1001
- return true;
1002
- try {
1003
- const date = this.adapter.epochDayToDate(day);
1004
- const isDateDisabled = this[WklyPickerInputsPropertyKeys.IsDateDisabled];
1005
- if (isDateDisabled &&
1006
- isDateDisabled(day, {
1007
- mode: this[WklyPickerInputsPropertyKeys.Mode],
1008
- endpoint: this.isRange
1009
- ? ((_a = this.drafts[0]) === null || _a === void 0 ? void 0 : _a.present) && !((_b = this.drafts[1]) === null || _b === void 0 ? void 0 : _b.present)
1010
- ? "end"
1011
- : "start"
1012
- : "single",
1013
- calendarDate: date,
1014
- }))
1015
- return true;
1016
- const min = this[WklyPickerInputsPropertyKeys.Min];
1017
- const max = this[WklyPickerInputsPropertyKeys.Max];
1018
- if (min && day < decodeIso(min).epochDay)
1019
- return true;
1020
- if (max && day > decodeIso(max).epochDay)
1021
- return true;
1022
- return false;
1023
- }
1024
- catch (_) {
1025
- return true;
1026
- }
1027
- }
1028
- select(day) {
1029
- if (this[WklyPickerInputsPropertyKeys.Disabled] || this.dayDisabled(day))
1030
- return;
1031
- this.focused = day;
1032
- const index = this.isRange && this.drafts[0].present && !this.drafts[1].present ? 1 : 0;
1033
- if (this.isRange && index === 0)
1034
- this.drafts[1].present = false;
1035
- delete this.drafts[index].unsupportedEpochDay;
1036
- this.drafts[index].date = this.adapter.epochDayToDate(day);
1037
- this.drafts[index].present = true;
1038
- this.orderDrafts();
1039
- this.renderRows();
1040
- this.finish();
1041
- if (this.presentation === "transient" &&
1042
- this[WklyPickerInputsPropertyKeys.Mode] === "date" &&
1043
- this.viewMode === "calendar")
1044
- this.submit("auto-submit");
1045
- }
1046
- key(event, day) {
1047
- let delta = 0;
1048
- if (event.key === "ArrowLeft")
1049
- delta = -1;
1050
- if (event.key === "ArrowRight")
1051
- delta = 1;
1052
- if (event.key === "ArrowUp")
1053
- delta = -7;
1054
- if (event.key === "ArrowDown")
1055
- delta = 7;
1056
- if (event.key === "PageUp")
1057
- delta = -7 * (event.shiftKey ? this.visibleCount : 1);
1058
- if (event.key === "PageDown")
1059
- delta = 7 * (event.shiftKey ? this.visibleCount : 1);
1060
- if (event.key === "Home") {
1061
- event.preventDefault();
1062
- this.scrollToEpochDay(this.today, { focus: true });
1063
- }
1064
- if (delta) {
1065
- event.preventDefault();
1066
- const target = day + delta;
1067
- if (target >= this.firstSupportedDay && target <= this.lastSupportedDay)
1068
- this.scrollToEpochDay(target, { focus: true });
1069
- }
1070
- }
1071
- position(day, preset = false, options = {}) {
1072
- day = Math.max(this.firstSupportedDay, Math.min(this.lastSupportedDay, day));
1073
- this.anchorWeek = absoluteWeekOf(day, this.effectiveOffset);
1074
- const viewportPreset = this[WklyPickerInputsPropertyKeys.ViewportPreset];
1075
- this.clipMonth = preset && viewportPreset.kind === "full-month";
1076
- if (preset && viewportPreset.kind !== "weeks") {
1077
- const d = this.adapter.epochDayToDate(day);
1078
- this.initialMonth = d.year + "/" + d.monthCode;
1079
- const [start, end] = calendarMonthBounds(this.adapter, day);
1080
- this.firstWeek = absoluteWeekOf(start, this.effectiveOffset);
1081
- this.visibleCount =
1082
- absoluteWeekOf(end, this.effectiveOffset) - this.firstWeek + 1;
1083
- if (viewportPreset.kind === "full-month-and-around" &&
1084
- !this.configErrors.length) {
1085
- const before = viewportPreset.extraWeeksBefore || 0, after = viewportPreset.extraWeeksAfter || 0;
1086
- this.firstWeek -= before;
1087
- this.visibleCount += before + after;
1088
- }
1089
- }
1090
- else {
1091
- if (viewportPreset.kind === "weeks")
1092
- this.visibleCount = this.configErrors.length
1093
- ? 6
1094
- : viewportPreset.visibleWeekCount;
1095
- this.firstWeek =
1096
- this.anchorWeek -
1097
- (options.align === "start"
1098
- ? 0
1099
- : options.align === "end"
1100
- ? this.visibleCount - 1
1101
- : Math.floor(this.visibleCount / 2));
1102
- }
1103
- this.firstWeek = this.clampFirstWeek(this.firstWeek);
1104
- this.baseWeek = this.firstWeek - 1000;
1105
- this.renderRows();
1106
- // Apply the new runway before writing scrollTop or locating a focus target.
1107
- this.changeDetector.detectChanges();
1108
- this.resetScroll();
1109
- }
1110
- resetScroll() {
1111
- // Round week boundaries to avoid scrollTop truncation under CSS zoom.
1112
- if (this.scroller)
1113
- this.scroller.nativeElement.scrollTop = Math.round(1000 * this.rowHeight);
1114
- }
1115
- scroll(event) {
1116
- const element = event.target;
1117
- this.snapPending = true;
1118
- this.scheduleSnap();
1119
- // Quantize displacement around the reset point, equally in both directions.
1120
- const relativeRows = element.scrollTop / this.rowHeight - 1000;
1121
- const index = 1000 + Math.sign(relativeRows) * Math.round(Math.abs(relativeRows));
1122
- const requestedFirst = this.baseWeek + index;
1123
- const first = this.clampFirstWeek(requestedFirst);
1124
- if (requestedFirst !== first) {
1125
- element.scrollTop = Math.round((first - this.baseWeek) * this.rowHeight);
1126
- }
1127
- if (first === this.firstWeek)
1128
- return;
1129
- this.clipMonth = false;
1130
- this.firstWeek = first;
1131
- this.anchorWeek = first + Math.floor(this.visibleCount / 2);
1132
- if (index < 100 || index > 1900) {
1133
- // Preserve signed displacement from this week; modulo turns fractional
1134
- // rounding just below a boundary into almost a full row after rebasing.
1135
- const offset = element.scrollTop - (first - this.baseWeek) * this.rowHeight;
1136
- this.baseWeek = first - 1000;
1137
- element.scrollTop = Math.round(1000 * this.rowHeight + offset);
1138
- }
1139
- this.renderRows();
1140
- }
1141
- scheduleSnap() {
1142
- if (this.scrollEndTimer)
1143
- clearTimeout(this.scrollEndTimer);
1144
- this.scrollEndTimer = setTimeout(() => this.snapWeek(), 200);
1145
- }
1146
- snapWeek() {
1147
- if (this.scrollEndTimer)
1148
- clearTimeout(this.scrollEndTimer);
1149
- this.scrollEndTimer = undefined;
1150
- if (!this.snapPending || !this.scroller)
1151
- return;
1152
- this.snapPending = false;
1153
- // Align the current virtual week without rebuilding or rebasing its rows.
1154
- const element = this.scroller.nativeElement;
1155
- const target = Math.round((this.firstWeek - this.baseWeek) * this.rowHeight);
1156
- if (element.scrollTop !== target)
1157
- element.scrollTop = target;
1158
- }
1159
- showFirstWeek(week) {
1160
- const first = this.clampFirstWeek(week);
1161
- if (first === this.firstWeek)
1162
- return;
1163
- this.clipMonth = false;
1164
- this.firstWeek = first;
1165
- this.anchorWeek = first + Math.floor(this.visibleCount / 2);
1166
- this.baseWeek = first - 1000;
1167
- this.renderRows();
1168
- this.resetScroll();
1169
- }
1170
- canMoveWeek(delta) {
1171
- return this.clampFirstWeek(this.firstWeek + delta) !== this.firstWeek;
1172
- }
1173
- moveWeek(delta) {
1174
- if (!this[WklyPickerInputsPropertyKeys.Disabled])
1175
- this.showFirstWeek(this.firstWeek + delta);
1176
- }
1177
- renderRows() {
1178
- // Keep the virtual scroll offset here; row data is shared across Angular versions.
1179
- const overscan = Math.max(0, Math.min(50, this[WklyPickerInputsPropertyKeys.OverscanWeeks] || 0));
1180
- const start = this.firstWeek - overscan;
1181
- this.paddingTop = (start - this.baseWeek) * this.rowHeight;
1182
- this.rows = createWeekRows({
1183
- generator: this.generator,
1184
- adapter: this.adapter,
1185
- startWeek: start,
1186
- count: this.visibleCount + 2 * overscan,
1187
- firstVisibleWeek: this.firstWeek,
1188
- firstSupportedDay: this.firstSupportedDay,
1189
- lastSupportedDay: this.lastSupportedDay,
1190
- clipMonth: this.clipMonth,
1191
- initialMonth: this.initialMonth,
1192
- weekLabelMode: this[WklyPickerInputsPropertyKeys.WeekLabelMode],
1193
- weekLabelFormatter: this[WklyPickerInputsPropertyKeys.WeekLabelFormatter] || null,
1194
- isDayDisabled: (day) => this.dayDisabled(day),
1195
- });
1196
- this[WklyPickerOutputsPropertyKeys.ViewportChange].emit({
1197
- firstVisibleAbsoluteWeek: this.firstWeek,
1198
- lastVisibleAbsoluteWeek: this.firstWeek + this.visibleCount - 1,
1199
- anchorAbsoluteWeek: this.anchorWeek,
1200
- });
1201
- }
1202
- // Retain day DOM nodes and keyboard focus when row metadata is regenerated.
1203
- trackCell(_i, cell) {
1204
- return cell.epochDay;
1205
- }
1206
- trackRow(_i, row) {
1207
- return row.week.absoluteWeek;
1208
- }
1209
- scrollToEpochDay(day, options = {}) {
1210
- integer(day);
1211
- this.adapter.epochDayToDate(day);
1212
- day = Math.max(this.firstSupportedDay, Math.min(this.lastSupportedDay, day));
1213
- // position renders synchronously; publish the tab stop before that render.
1214
- if (options.focus)
1215
- this.focused = day;
1216
- this.position(day, false, options);
1217
- if (options.select)
1218
- this.select(day);
1219
- if (options.focus)
1220
- this.focusDay();
1221
- }
1222
- scrollToAbsoluteWeek(week, options = {}) {
1223
- // A boundary week can start before the adapter's first supported day.
1224
- const first = firstEpochDayOf(week, this.effectiveOffset);
1225
- this.scrollToEpochDay(week === this.firstSupportedWeek
1226
- ? Math.max(first, this.firstSupportedDay)
1227
- : first, options);
1228
- }
1229
- scrollToCalendarDate(date, options = {}) {
1230
- this.scrollToEpochDay(this.adapter.dateToEpochDay(date), options);
1231
- }
1232
- scrollToValue(value, options = {}) {
1233
- this.scrollToEpochDay(decodeIso(value).epochDay, options);
1234
- }
1235
- focusDay() {
1236
- if (!this.browser)
1237
- return;
1238
- setTimeout(() => {
1239
- var _a;
1240
- if (this.destroyed)
1241
- return;
1242
- this.changeDetector.detectChanges();
1243
- const day = this.host.nativeElement.querySelector('[data-day="' + this.focused + '"]');
1244
- const fallback = this.host.nativeElement.querySelector("button:not(:disabled),input:not(:disabled)");
1245
- (_a = (day || fallback)) === null || _a === void 0 ? void 0 : _a.focus({ preventScroll: true });
1246
- });
1247
- }
1248
- }
1249
- WklyDateTimePickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyDateTimePickerComponent, deps: [{ token: LOCALE_ID }, { token: WKLY_CONFIG }, { token: WKLY_CLOCK }, { token: WKLY_LOCALIZATION }, { token: WKLY_TRANSLATIONS }, { token: PLATFORM_ID }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1250
- WklyDateTimePickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: WklyDateTimePickerComponent, selector: "wkly-datetime-picker", providers: [
1251
- {
1252
- provide: NG_VALUE_ACCESSOR,
1253
- useExisting: forwardRef(() => WklyDateTimePickerComponent),
1254
- multi: true,
1255
- },
1256
- {
1257
- provide: NG_VALIDATORS,
1258
- useExisting: forwardRef(() => WklyDateTimePickerComponent),
1259
- multi: true,
1260
- },
1261
- ], viewQueries: [{ propertyName: "scroller", first: true, predicate: ["scroller"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<section\n class=\"wkly\"\n [attr.dir]=\"direction\"\n [attr.aria-label]=\"\n this[WklyPickerInputsPropertyKeys.AriaLabel] || 'Date and time picker'\n \"\n [attr.aria-describedby]=\"this[WklyPickerInputsPropertyKeys.AriaDescribedBy]\"\n (focusout)=\"touched()\"\n>\n <header class=\"toolbar\">\n <button\n *ngIf=\"hasDate\"\n type=\"button\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-label]=\"t(viewMode === 'calendar' ? 'manual' : 'calendar')\"\n (click)=\"toggleView()\"\n >\n {{ viewMode === \"calendar\" ? \"\u2637\" : \"\u25A6\" }}\n </button>\n <span *ngIf=\"hasDate\" class=\"year-control\">{{ title }}</span>\n <span class=\"spacer\"></span\n ><button\n type=\"button\"\n class=\"now\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n (click)=\"now()\"\n >\n {{ t(\"now\") }}\n </button>\n <button\n *ngIf=\"presentation === 'transient'\"\n type=\"button\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-label]=\"t('close')\"\n (click)=\"cancel()\"\n >\n \u00D7\n </button>\n </header>\n <ng-container *ngIf=\"hasDate && viewMode === 'calendar'\">\n <div\n role=\"grid\"\n [attr.aria-label]=\"\n this[WklyPickerInputsPropertyKeys.AriaLabel] || 'Calendar'\n \"\n [attr.aria-multiselectable]=\"isRange\"\n >\n <div\n role=\"row\"\n class=\"week-head\"\n [class.no-label]=\"\n compact ||\n (this[WklyPickerInputsPropertyKeys.WeekLabelMode] === 'hidden' &&\n !this[WklyPickerInputsPropertyKeys.WeekLabelFormatter])\n \"\n >\n <span\n *ngIf=\"\n !compact &&\n (this[WklyPickerInputsPropertyKeys.WeekLabelMode] !== 'hidden' ||\n this[WklyPickerInputsPropertyKeys.WeekLabelFormatter])\n \"\n role=\"columnheader\"\n aria-label=\"Week\"\n ></span\n ><span *ngFor=\"let day of weekdays\" role=\"columnheader\">{{ day }}</span>\n </div>\n <div\n #scroller\n class=\"week-scroll\"\n [style.height.px]=\"visibleCount * rowHeight\"\n (scroll)=\"scroll($event)\"\n (scrollend)=\"snapWeek()\"\n >\n <div [style.height.px]=\"scrollHeight\" class=\"scroll-space\">\n <div class=\"rows\" [style.top.px]=\"paddingTop\">\n <div\n *ngFor=\"let row of rows; trackBy: trackRow\"\n role=\"row\"\n class=\"week-row\"\n [class.no-label]=\"\n compact ||\n (this[WklyPickerInputsPropertyKeys.WeekLabelMode] ===\n 'hidden' &&\n !this[WklyPickerInputsPropertyKeys.WeekLabelFormatter])\n \"\n >\n <span\n *ngIf=\"\n !compact &&\n (this[WklyPickerInputsPropertyKeys.WeekLabelMode] !==\n 'hidden' ||\n this[WklyPickerInputsPropertyKeys.WeekLabelFormatter])\n \"\n role=\"rowheader\"\n class=\"week-number\"\n >{{ row.label }}</span\n >\n <div\n *ngFor=\"\n let cell of row.cells;\n let dayIndex = index;\n trackBy: trackCell\n \"\n role=\"gridcell\"\n [attr.data-weekday-index]=\"dayIndex\"\n [attr.aria-colindex]=\"\n dayIndex +\n (compact ||\n (this[WklyPickerInputsPropertyKeys.WeekLabelMode] ===\n 'hidden' &&\n !this[WklyPickerInputsPropertyKeys.WeekLabelFormatter])\n ? 1\n : 2)\n \"\n [attr.aria-selected]=\"selected(cell.epochDay)\"\n [attr.aria-disabled]=\"\n cell.disabled || this[WklyPickerInputsPropertyKeys.Disabled]\n \"\n [class.range]=\"inRange(cell.epochDay)\"\n [class.hidden]=\"cell.hidden\"\n [class.odd-month]=\"cell.date && cell.date.month % 2 === 1\"\n >\n <span [class]=\"'annotation annotation--' + dayIndex\">{{\n cell.annotation\n }}</span>\n <button\n type=\"button\"\n class=\"day\"\n [attr.data-day]=\"cell.epochDay\"\n [attr.aria-label]=\"cell.accessible\"\n [attr.aria-current]=\"cell.epochDay === today ? 'date' : null\"\n [attr.aria-disabled]=\"\n cell.disabled || this[WklyPickerInputsPropertyKeys.Disabled]\n \"\n [attr.tabindex]=\"\n !cell.hidden && cell.epochDay === focused ? 0 : -1\n \"\n [class.selected]=\"selected(cell.epochDay)\"\n [class.today]=\"cell.epochDay === today\"\n (focus)=\"focused = cell.epochDay\"\n (click)=\"select(cell.epochDay)\"\n (keydown)=\"key($event, cell.epochDay)\"\n >\n {{ cell.label }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"week-navigation\">\n <button\n type=\"button\"\n [disabled]=\"\n this[WklyPickerInputsPropertyKeys.Disabled] || !canMoveWeek(-1)\n \"\n [attr.aria-label]=\"t('previous')\"\n (click)=\"moveWeek(-1)\"\n >\n \u2191</button\n ><span>{{ title }}</span\n ><button\n type=\"button\"\n [disabled]=\"\n this[WklyPickerInputsPropertyKeys.Disabled] || !canMoveWeek(1)\n \"\n [attr.aria-label]=\"t('next')\"\n (click)=\"moveWeek(1)\"\n >\n \u2193\n </button>\n </div>\n </ng-container>\n <ng-container\n *ngFor=\"let draft of drafts; let i = index; trackBy: trackDraft\"\n >\n <fieldset\n *ngIf=\"(i === 0 || isRange) && (hasTime || viewMode === 'manual')\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-label]=\"isRange ? t(i === 0 ? 'start' : 'end') : null\"\n >\n <legend *ngIf=\"isRange\">\n <ng-container\n *ngIf=\"\n i === 1 && hasDate && viewMode === 'manual';\n else endpointLabel\n \"\n >\n <span class=\"end-view-toggle\">\n <button\n type=\"button\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-pressed]=\"endView === 'date'\"\n (click)=\"toggleEndView('date')\"\n >\n {{ t(\"end\") }}\n </button>\n <button\n type=\"button\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-pressed]=\"endView === 'days'\"\n (click)=\"toggleEndView('days')\"\n >\n {{ inDaysLabel }}\n </button>\n </span>\n </ng-container>\n <ng-template #endpointLabel>{{\n t(i === 0 ? \"start\" : \"end\")\n }}</ng-template>\n </legend>\n <div\n *ngIf=\"\n i === 1 && hasDate && viewMode === 'manual' && endView === 'days'\n \"\n class=\"date-fields in-days-fields\"\n >\n <span class=\"resulting-end-date\" [attr.aria-label]=\"t('endDate')\">{{\n resultingEndDate\n }}</span>\n <wkly-field\n [label]=\"t('days')\"\n [hideLabel]=\"true\"\n [previousLabel]=\"t('daysPrevious')\"\n [nextLabel]=\"t('daysNext')\"\n [locale]=\"effectiveLocale\"\n [value]=\"inDays\"\n [min]=\"-9999\"\n [max]=\"9999\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"days($event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n </div>\n <div\n *ngIf=\"\n hasDate && viewMode === 'manual' && (i === 0 || endView === 'date')\n \"\n class=\"date-fields\"\n >\n <wkly-field\n [label]=\"t('day')\"\n [locale]=\"effectiveLocale\"\n [value]=\"draft.date.day\"\n [min]=\"1\"\n [max]=\"31\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"field(i, 'day', $event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n <wkly-field\n [label]=\"t('month')\"\n [locale]=\"effectiveLocale\"\n [value]=\"draft.date.month\"\n [min]=\"1\"\n [max]=\"monthCount(draft)\"\n [labels]=\"months(draft)\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"field(i, 'month', $event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n <wkly-field\n [label]=\"t('year')\"\n [locale]=\"effectiveLocale\"\n [value]=\"draft.date.year\"\n [min]=\"adapter.supportedYearRange[0]\"\n [max]=\"adapter.supportedYearRange[1]\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"field(i, 'year', $event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n </div>\n <div\n *ngIf=\"hasTime\"\n class=\"time-fields\"\n [class.seconds]=\"this[WklyPickerInputsPropertyKeys.ShowSeconds]\"\n >\n <wkly-field\n [label]=\"t('hour')\"\n [locale]=\"effectiveLocale\"\n [value]=\"displayHour(draft)\"\n [min]=\"effectiveHourCycle === 'h12' ? 1 : 0\"\n [max]=\"effectiveHourCycle === 'h12' ? 12 : 23\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"field(i, 'hour', $event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n <wkly-field\n [label]=\"t('minute')\"\n [locale]=\"effectiveLocale\"\n [value]=\"draft.minute\"\n [max]=\"59\"\n [step]=\"\n this[WklyPickerInputsPropertyKeys.MinuteStep] > 0 &&\n 60 % this[WklyPickerInputsPropertyKeys.MinuteStep] === 0\n ? this[WklyPickerInputsPropertyKeys.MinuteStep]\n : 1\n \"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"field(i, 'minute', $event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n <wkly-field\n *ngIf=\"this[WklyPickerInputsPropertyKeys.ShowSeconds]\"\n [label]=\"t('second')\"\n [locale]=\"effectiveLocale\"\n [value]=\"draft.second\"\n [max]=\"59\"\n [step]=\"\n this[WklyPickerInputsPropertyKeys.SecondStep] > 0 &&\n 60 % this[WklyPickerInputsPropertyKeys.SecondStep] === 0\n ? this[WklyPickerInputsPropertyKeys.SecondStep]\n : 1\n \"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"field(i, 'second', $event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n <div class=\"period\">\n <button\n *ngIf=\"\n effectiveHourCycle === 'h12' ||\n this[WklyPickerInputsPropertyKeys.HourCycle] === 'switchable'\n \"\n type=\"button\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-pressed]=\"\n effectiveHourCycle === 'h12' && (draft.hour || 0) < 12\n \"\n (click)=\"period(i, 'am')\"\n >\n {{ t(\"am\") }}</button\n ><button\n type=\"button\"\n [disabled]=\"\n this[WklyPickerInputsPropertyKeys.Disabled] ||\n this[WklyPickerInputsPropertyKeys.HourCycle] !== 'switchable'\n \"\n [attr.aria-pressed]=\"effectiveHourCycle === 'h24'\"\n (click)=\"period(i, '24')\"\n >\n 24</button\n ><button\n *ngIf=\"\n effectiveHourCycle === 'h12' ||\n this[WklyPickerInputsPropertyKeys.HourCycle] === 'switchable'\n \"\n type=\"button\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-pressed]=\"\n effectiveHourCycle === 'h12' && (draft.hour || 0) >= 12\n \"\n (click)=\"period(i, 'pm')\"\n >\n {{ t(\"pm\") }}\n </button>\n </div>\n </div>\n </fieldset>\n </ng-container>\n <div class=\"validation\" role=\"status\" aria-live=\"polite\">\n <p *ngFor=\"let err of errors\">! {{ t(err.messageKey) }}</p>\n </div>\n <footer *ngIf=\"submitVisible\">\n <button\n type=\"button\"\n class=\"confirm\"\n [disabled]=\"!canSubmit\"\n (click)=\"submit()\"\n >\n {{ t(\"confirm\") }}\n </button>\n </footer>\n</section>\n", styles: [":host{display:block;width:100%;box-sizing:border-box;--wkly-background-color: #fff;--wkly-background-color-alternate: #fafafa;--wkly-text-color: #192c28;--wkly-muted-color: #52635e;--wkly-border-color: #dce5e1;--wkly-accent-color: #176c55;--wkly-accent-color-alternate: #6ea494;--wkly-accent-text-color: #fff;--wkly-range-color: #e5f1ee;--wkly-error-color: #b42318;--wkly-focus-color: #245bd6;--wkly-size-multiplier: 1;--wkly-size-unit: 3.5em;color:var(--wkly-text-color);font:14px/1.4 system-ui,sans-serif;container-type:inline-size}.wkly{background:var(--wkly-background-color);border:1px solid var(--wkly-border-color);border-radius:14px;overflow:hidden;min-width:0;font-size:calc(14px*clamp(1,var(--wkly-size-multiplier),1.5))}button{font:inherit;color:inherit;min-width:var(--wkly-size-unit);min-height:var(--wkly-size-unit);border:0;background:transparent;border-radius:8px;cursor:pointer}@media (hover: hover) and (pointer: fine){button:hover:not(:disabled):not([aria-disabled=\"true\"]):not(.selected){background:var(--wkly-accent-color-alternate)}}button:disabled,button[aria-disabled=true]{opacity:.4;cursor:default}button:focus-visible{outline:2px solid var(--wkly-focus-color);outline-offset:-2px}.toolbar{display:flex;align-items:center;padding:8px;gap:3px;border-bottom:1px solid var(--wkly-border-color)}.spacer{flex:1}.year-control{padding:0 6px;font-weight:650;text-align:start;line-height:1.2}.now{color:var(--wkly-accent-color);font-weight:650}.week-head,.week-row{display:grid;grid-template-columns:28px repeat(7,minmax(0,1fr))}.week-head{font-size:.85em;color:var(--wkly-muted-color);height:34px;align-items:center;text-align:center}.week-row{height:calc(var(--wkly-size-unit) * clamp(1,var(--wkly-size-multiplier),1));align-items:end}.no-label{grid-template-columns:repeat(7,minmax(0,1fr))}.week-scroll{overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;overflow-anchor:none;scrollbar-width:thin;max-height:65vh;touch-action:pan-y}.scroll-space{position:relative}.rows{position:absolute;left:0;right:0}.week-number{font-size:.85em;text-align:center;align-self:end;line-height:var(--wkly-size-unit);color:var(--wkly-muted-color)}[role=gridcell]{position:relative;min-width:0;height:var(--wkly-size-unit);text-align:center}[role=gridcell].odd-month:not(.range):not(.today){background:var(--wkly-background-color-alternate)}.day{width:100%;min-width:0;height:var(--wkly-size-unit);padding:0;border-radius:8px}.annotation{position:absolute;bottom:.25em;white-space:nowrap;font-size:1.25em;font-weight:650;line-height:1;pointer-events:none;z-index:1;color:var(--wkly-muted-color);color:color-mix(in srgb,var(--wkly-muted-color) 50%,transparent);text-shadow:0 0 2px --wkly-background-color,0 0 4px --wkly-background-color}.odd-month .annotation{text-shadow:0 0 2px --wkly-background-color-alternate,0 0 4px --wkly-background-color-alternate}.annotation:empty{display:none}.annotation--0{inset-inline-start:10%;bottom:1.75em}.annotation--1{inset-inline-start:-5%}.annotation--2{inset-inline-start:-20%}.annotation--3{inset-inline-start:-50%;inset-inline-end:-50%}.annotation--4{inset-inline-end:-20%}.annotation--5{inset-inline-end:-5%}.annotation--6{inset-inline-end:10%}.range{background:var(--wkly-range-color)}.day.selected{background:var(--wkly-accent-color);color:var(--wkly-accent-text-color);font-weight:700}.today:after{content:\"\";display:block;width:5px;height:5px;background:currentColor;border-radius:50%;position:absolute;bottom:2px;left:calc(50% - 2px)}.today{font-weight:750;box-shadow:inset 0 0 0 1px var(--wkly-accent-color)}.hidden{visibility:hidden}.week-navigation{display:flex;align-items:center;justify-content:space-between;border-top:1px solid var(--wkly-border-color);font-size:.85em;color:var(--wkly-muted-color)}fieldset{border:0;padding:0 12px;margin:0;min-width:0}legend{padding-top:.85em;font-weight:650;color:var(--wkly-accent-color)}.date-fields{display:grid;grid-template-columns:1fr 2fr 1.4fr;gap:7px;padding:12px 0}.end-view-toggle{display:inline-flex}.end-view-toggle button{min-height:0;min-width:0;padding:0 6px;border-radius:0;line-height:inherit}.end-view-toggle button:first-child{padding-inline-start:0}.end-view-toggle button+button{border-inline-start:1px solid var(--wkly-text-color)}.end-view-toggle button[aria-pressed=false]{color:var(--wkly-muted-color);font-weight:400}.in-days-fields{grid-template-columns:minmax(0,1fr);gap:0;text-align:center}.resulting-end-date{font-size:11px;color:var(--wkly-muted-color);height:1.4em;margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.time-fields{display:grid;grid-template-columns:1fr 1fr 52px;gap:8px;padding:14px 0;border-top:1px solid var(--wkly-border-color)}.time-fields.seconds{grid-template-columns:1fr 1fr 1fr 48px}.period{display:flex;flex-direction:column;justify-content:center;gap:2px;padding-top:1.25em}.period button{font-size:.85em}.period [aria-pressed=true]{background:var(--wkly-range-color);box-shadow:inset 0 0 0 1px var(--wkly-accent-color);font-weight:700}.validation{color:var(--wkly-error-color);font-size:.85em}.validation p{margin:.5em .85em}footer{padding:12px;border-top:1px solid var(--wkly-border-color)}.confirm{background:var(--wkly-accent-color);color:var(--wkly-accent-text-color);width:100%;font-weight:650}@media (forced-colors: active){.day.selected{outline:2px solid Highlight}.range{border-bottom:2px solid Highlight}.today{outline:1px dashed CanvasText}}@media (prefers-reduced-motion: reduce){*{scroll-behavior:auto!important;animation:none!important}}\n"], dependencies: [{ 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: WklyFieldComponent, selector: "wkly-field", inputs: ["value", "label", "hideLabel", "previousLabel", "nextLabel", "min", "max", "step", "locale", "disabled", "invalid", "labels"], outputs: ["valueChange", "complete"] }] });
1262
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyDateTimePickerComponent, decorators: [{
1263
- type: Component,
1264
- args: [{ selector: "wkly-datetime-picker", providers: [
1265
- {
1266
- provide: NG_VALUE_ACCESSOR,
1267
- useExisting: forwardRef(() => WklyDateTimePickerComponent),
1268
- multi: true,
1269
- },
1270
- {
1271
- provide: NG_VALIDATORS,
1272
- useExisting: forwardRef(() => WklyDateTimePickerComponent),
1273
- multi: true,
1274
- },
1275
- ], template: "<section\n class=\"wkly\"\n [attr.dir]=\"direction\"\n [attr.aria-label]=\"\n this[WklyPickerInputsPropertyKeys.AriaLabel] || 'Date and time picker'\n \"\n [attr.aria-describedby]=\"this[WklyPickerInputsPropertyKeys.AriaDescribedBy]\"\n (focusout)=\"touched()\"\n>\n <header class=\"toolbar\">\n <button\n *ngIf=\"hasDate\"\n type=\"button\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-label]=\"t(viewMode === 'calendar' ? 'manual' : 'calendar')\"\n (click)=\"toggleView()\"\n >\n {{ viewMode === \"calendar\" ? \"\u2637\" : \"\u25A6\" }}\n </button>\n <span *ngIf=\"hasDate\" class=\"year-control\">{{ title }}</span>\n <span class=\"spacer\"></span\n ><button\n type=\"button\"\n class=\"now\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n (click)=\"now()\"\n >\n {{ t(\"now\") }}\n </button>\n <button\n *ngIf=\"presentation === 'transient'\"\n type=\"button\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-label]=\"t('close')\"\n (click)=\"cancel()\"\n >\n \u00D7\n </button>\n </header>\n <ng-container *ngIf=\"hasDate && viewMode === 'calendar'\">\n <div\n role=\"grid\"\n [attr.aria-label]=\"\n this[WklyPickerInputsPropertyKeys.AriaLabel] || 'Calendar'\n \"\n [attr.aria-multiselectable]=\"isRange\"\n >\n <div\n role=\"row\"\n class=\"week-head\"\n [class.no-label]=\"\n compact ||\n (this[WklyPickerInputsPropertyKeys.WeekLabelMode] === 'hidden' &&\n !this[WklyPickerInputsPropertyKeys.WeekLabelFormatter])\n \"\n >\n <span\n *ngIf=\"\n !compact &&\n (this[WklyPickerInputsPropertyKeys.WeekLabelMode] !== 'hidden' ||\n this[WklyPickerInputsPropertyKeys.WeekLabelFormatter])\n \"\n role=\"columnheader\"\n aria-label=\"Week\"\n ></span\n ><span *ngFor=\"let day of weekdays\" role=\"columnheader\">{{ day }}</span>\n </div>\n <div\n #scroller\n class=\"week-scroll\"\n [style.height.px]=\"visibleCount * rowHeight\"\n (scroll)=\"scroll($event)\"\n (scrollend)=\"snapWeek()\"\n >\n <div [style.height.px]=\"scrollHeight\" class=\"scroll-space\">\n <div class=\"rows\" [style.top.px]=\"paddingTop\">\n <div\n *ngFor=\"let row of rows; trackBy: trackRow\"\n role=\"row\"\n class=\"week-row\"\n [class.no-label]=\"\n compact ||\n (this[WklyPickerInputsPropertyKeys.WeekLabelMode] ===\n 'hidden' &&\n !this[WklyPickerInputsPropertyKeys.WeekLabelFormatter])\n \"\n >\n <span\n *ngIf=\"\n !compact &&\n (this[WklyPickerInputsPropertyKeys.WeekLabelMode] !==\n 'hidden' ||\n this[WklyPickerInputsPropertyKeys.WeekLabelFormatter])\n \"\n role=\"rowheader\"\n class=\"week-number\"\n >{{ row.label }}</span\n >\n <div\n *ngFor=\"\n let cell of row.cells;\n let dayIndex = index;\n trackBy: trackCell\n \"\n role=\"gridcell\"\n [attr.data-weekday-index]=\"dayIndex\"\n [attr.aria-colindex]=\"\n dayIndex +\n (compact ||\n (this[WklyPickerInputsPropertyKeys.WeekLabelMode] ===\n 'hidden' &&\n !this[WklyPickerInputsPropertyKeys.WeekLabelFormatter])\n ? 1\n : 2)\n \"\n [attr.aria-selected]=\"selected(cell.epochDay)\"\n [attr.aria-disabled]=\"\n cell.disabled || this[WklyPickerInputsPropertyKeys.Disabled]\n \"\n [class.range]=\"inRange(cell.epochDay)\"\n [class.hidden]=\"cell.hidden\"\n [class.odd-month]=\"cell.date && cell.date.month % 2 === 1\"\n >\n <span [class]=\"'annotation annotation--' + dayIndex\">{{\n cell.annotation\n }}</span>\n <button\n type=\"button\"\n class=\"day\"\n [attr.data-day]=\"cell.epochDay\"\n [attr.aria-label]=\"cell.accessible\"\n [attr.aria-current]=\"cell.epochDay === today ? 'date' : null\"\n [attr.aria-disabled]=\"\n cell.disabled || this[WklyPickerInputsPropertyKeys.Disabled]\n \"\n [attr.tabindex]=\"\n !cell.hidden && cell.epochDay === focused ? 0 : -1\n \"\n [class.selected]=\"selected(cell.epochDay)\"\n [class.today]=\"cell.epochDay === today\"\n (focus)=\"focused = cell.epochDay\"\n (click)=\"select(cell.epochDay)\"\n (keydown)=\"key($event, cell.epochDay)\"\n >\n {{ cell.label }}\n </button>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"week-navigation\">\n <button\n type=\"button\"\n [disabled]=\"\n this[WklyPickerInputsPropertyKeys.Disabled] || !canMoveWeek(-1)\n \"\n [attr.aria-label]=\"t('previous')\"\n (click)=\"moveWeek(-1)\"\n >\n \u2191</button\n ><span>{{ title }}</span\n ><button\n type=\"button\"\n [disabled]=\"\n this[WklyPickerInputsPropertyKeys.Disabled] || !canMoveWeek(1)\n \"\n [attr.aria-label]=\"t('next')\"\n (click)=\"moveWeek(1)\"\n >\n \u2193\n </button>\n </div>\n </ng-container>\n <ng-container\n *ngFor=\"let draft of drafts; let i = index; trackBy: trackDraft\"\n >\n <fieldset\n *ngIf=\"(i === 0 || isRange) && (hasTime || viewMode === 'manual')\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-label]=\"isRange ? t(i === 0 ? 'start' : 'end') : null\"\n >\n <legend *ngIf=\"isRange\">\n <ng-container\n *ngIf=\"\n i === 1 && hasDate && viewMode === 'manual';\n else endpointLabel\n \"\n >\n <span class=\"end-view-toggle\">\n <button\n type=\"button\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-pressed]=\"endView === 'date'\"\n (click)=\"toggleEndView('date')\"\n >\n {{ t(\"end\") }}\n </button>\n <button\n type=\"button\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-pressed]=\"endView === 'days'\"\n (click)=\"toggleEndView('days')\"\n >\n {{ inDaysLabel }}\n </button>\n </span>\n </ng-container>\n <ng-template #endpointLabel>{{\n t(i === 0 ? \"start\" : \"end\")\n }}</ng-template>\n </legend>\n <div\n *ngIf=\"\n i === 1 && hasDate && viewMode === 'manual' && endView === 'days'\n \"\n class=\"date-fields in-days-fields\"\n >\n <span class=\"resulting-end-date\" [attr.aria-label]=\"t('endDate')\">{{\n resultingEndDate\n }}</span>\n <wkly-field\n [label]=\"t('days')\"\n [hideLabel]=\"true\"\n [previousLabel]=\"t('daysPrevious')\"\n [nextLabel]=\"t('daysNext')\"\n [locale]=\"effectiveLocale\"\n [value]=\"inDays\"\n [min]=\"-9999\"\n [max]=\"9999\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"days($event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n </div>\n <div\n *ngIf=\"\n hasDate && viewMode === 'manual' && (i === 0 || endView === 'date')\n \"\n class=\"date-fields\"\n >\n <wkly-field\n [label]=\"t('day')\"\n [locale]=\"effectiveLocale\"\n [value]=\"draft.date.day\"\n [min]=\"1\"\n [max]=\"31\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"field(i, 'day', $event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n <wkly-field\n [label]=\"t('month')\"\n [locale]=\"effectiveLocale\"\n [value]=\"draft.date.month\"\n [min]=\"1\"\n [max]=\"monthCount(draft)\"\n [labels]=\"months(draft)\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"field(i, 'month', $event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n <wkly-field\n [label]=\"t('year')\"\n [locale]=\"effectiveLocale\"\n [value]=\"draft.date.year\"\n [min]=\"adapter.supportedYearRange[0]\"\n [max]=\"adapter.supportedYearRange[1]\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"field(i, 'year', $event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n </div>\n <div\n *ngIf=\"hasTime\"\n class=\"time-fields\"\n [class.seconds]=\"this[WklyPickerInputsPropertyKeys.ShowSeconds]\"\n >\n <wkly-field\n [label]=\"t('hour')\"\n [locale]=\"effectiveLocale\"\n [value]=\"displayHour(draft)\"\n [min]=\"effectiveHourCycle === 'h12' ? 1 : 0\"\n [max]=\"effectiveHourCycle === 'h12' ? 12 : 23\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"field(i, 'hour', $event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n <wkly-field\n [label]=\"t('minute')\"\n [locale]=\"effectiveLocale\"\n [value]=\"draft.minute\"\n [max]=\"59\"\n [step]=\"\n this[WklyPickerInputsPropertyKeys.MinuteStep] > 0 &&\n 60 % this[WklyPickerInputsPropertyKeys.MinuteStep] === 0\n ? this[WklyPickerInputsPropertyKeys.MinuteStep]\n : 1\n \"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"field(i, 'minute', $event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n <wkly-field\n *ngIf=\"this[WklyPickerInputsPropertyKeys.ShowSeconds]\"\n [label]=\"t('second')\"\n [locale]=\"effectiveLocale\"\n [value]=\"draft.second\"\n [max]=\"59\"\n [step]=\"\n this[WklyPickerInputsPropertyKeys.SecondStep] > 0 &&\n 60 % this[WklyPickerInputsPropertyKeys.SecondStep] === 0\n ? this[WklyPickerInputsPropertyKeys.SecondStep]\n : 1\n \"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [invalid]=\"!!errors.length\"\n (valueChange)=\"field(i, 'second', $event)\"\n (complete)=\"finish()\"\n ></wkly-field>\n <div class=\"period\">\n <button\n *ngIf=\"\n effectiveHourCycle === 'h12' ||\n this[WklyPickerInputsPropertyKeys.HourCycle] === 'switchable'\n \"\n type=\"button\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-pressed]=\"\n effectiveHourCycle === 'h12' && (draft.hour || 0) < 12\n \"\n (click)=\"period(i, 'am')\"\n >\n {{ t(\"am\") }}</button\n ><button\n type=\"button\"\n [disabled]=\"\n this[WklyPickerInputsPropertyKeys.Disabled] ||\n this[WklyPickerInputsPropertyKeys.HourCycle] !== 'switchable'\n \"\n [attr.aria-pressed]=\"effectiveHourCycle === 'h24'\"\n (click)=\"period(i, '24')\"\n >\n 24</button\n ><button\n *ngIf=\"\n effectiveHourCycle === 'h12' ||\n this[WklyPickerInputsPropertyKeys.HourCycle] === 'switchable'\n \"\n type=\"button\"\n [disabled]=\"this[WklyPickerInputsPropertyKeys.Disabled]\"\n [attr.aria-pressed]=\"\n effectiveHourCycle === 'h12' && (draft.hour || 0) >= 12\n \"\n (click)=\"period(i, 'pm')\"\n >\n {{ t(\"pm\") }}\n </button>\n </div>\n </div>\n </fieldset>\n </ng-container>\n <div class=\"validation\" role=\"status\" aria-live=\"polite\">\n <p *ngFor=\"let err of errors\">! {{ t(err.messageKey) }}</p>\n </div>\n <footer *ngIf=\"submitVisible\">\n <button\n type=\"button\"\n class=\"confirm\"\n [disabled]=\"!canSubmit\"\n (click)=\"submit()\"\n >\n {{ t(\"confirm\") }}\n </button>\n </footer>\n</section>\n", styles: [":host{display:block;width:100%;box-sizing:border-box;--wkly-background-color: #fff;--wkly-background-color-alternate: #fafafa;--wkly-text-color: #192c28;--wkly-muted-color: #52635e;--wkly-border-color: #dce5e1;--wkly-accent-color: #176c55;--wkly-accent-color-alternate: #6ea494;--wkly-accent-text-color: #fff;--wkly-range-color: #e5f1ee;--wkly-error-color: #b42318;--wkly-focus-color: #245bd6;--wkly-size-multiplier: 1;--wkly-size-unit: 3.5em;color:var(--wkly-text-color);font:14px/1.4 system-ui,sans-serif;container-type:inline-size}.wkly{background:var(--wkly-background-color);border:1px solid var(--wkly-border-color);border-radius:14px;overflow:hidden;min-width:0;font-size:calc(14px*clamp(1,var(--wkly-size-multiplier),1.5))}button{font:inherit;color:inherit;min-width:var(--wkly-size-unit);min-height:var(--wkly-size-unit);border:0;background:transparent;border-radius:8px;cursor:pointer}@media (hover: hover) and (pointer: fine){button:hover:not(:disabled):not([aria-disabled=\"true\"]):not(.selected){background:var(--wkly-accent-color-alternate)}}button:disabled,button[aria-disabled=true]{opacity:.4;cursor:default}button:focus-visible{outline:2px solid var(--wkly-focus-color);outline-offset:-2px}.toolbar{display:flex;align-items:center;padding:8px;gap:3px;border-bottom:1px solid var(--wkly-border-color)}.spacer{flex:1}.year-control{padding:0 6px;font-weight:650;text-align:start;line-height:1.2}.now{color:var(--wkly-accent-color);font-weight:650}.week-head,.week-row{display:grid;grid-template-columns:28px repeat(7,minmax(0,1fr))}.week-head{font-size:.85em;color:var(--wkly-muted-color);height:34px;align-items:center;text-align:center}.week-row{height:calc(var(--wkly-size-unit) * clamp(1,var(--wkly-size-multiplier),1));align-items:end}.no-label{grid-template-columns:repeat(7,minmax(0,1fr))}.week-scroll{overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;overflow-anchor:none;scrollbar-width:thin;max-height:65vh;touch-action:pan-y}.scroll-space{position:relative}.rows{position:absolute;left:0;right:0}.week-number{font-size:.85em;text-align:center;align-self:end;line-height:var(--wkly-size-unit);color:var(--wkly-muted-color)}[role=gridcell]{position:relative;min-width:0;height:var(--wkly-size-unit);text-align:center}[role=gridcell].odd-month:not(.range):not(.today){background:var(--wkly-background-color-alternate)}.day{width:100%;min-width:0;height:var(--wkly-size-unit);padding:0;border-radius:8px}.annotation{position:absolute;bottom:.25em;white-space:nowrap;font-size:1.25em;font-weight:650;line-height:1;pointer-events:none;z-index:1;color:var(--wkly-muted-color);color:color-mix(in srgb,var(--wkly-muted-color) 50%,transparent);text-shadow:0 0 2px --wkly-background-color,0 0 4px --wkly-background-color}.odd-month .annotation{text-shadow:0 0 2px --wkly-background-color-alternate,0 0 4px --wkly-background-color-alternate}.annotation:empty{display:none}.annotation--0{inset-inline-start:10%;bottom:1.75em}.annotation--1{inset-inline-start:-5%}.annotation--2{inset-inline-start:-20%}.annotation--3{inset-inline-start:-50%;inset-inline-end:-50%}.annotation--4{inset-inline-end:-20%}.annotation--5{inset-inline-end:-5%}.annotation--6{inset-inline-end:10%}.range{background:var(--wkly-range-color)}.day.selected{background:var(--wkly-accent-color);color:var(--wkly-accent-text-color);font-weight:700}.today:after{content:\"\";display:block;width:5px;height:5px;background:currentColor;border-radius:50%;position:absolute;bottom:2px;left:calc(50% - 2px)}.today{font-weight:750;box-shadow:inset 0 0 0 1px var(--wkly-accent-color)}.hidden{visibility:hidden}.week-navigation{display:flex;align-items:center;justify-content:space-between;border-top:1px solid var(--wkly-border-color);font-size:.85em;color:var(--wkly-muted-color)}fieldset{border:0;padding:0 12px;margin:0;min-width:0}legend{padding-top:.85em;font-weight:650;color:var(--wkly-accent-color)}.date-fields{display:grid;grid-template-columns:1fr 2fr 1.4fr;gap:7px;padding:12px 0}.end-view-toggle{display:inline-flex}.end-view-toggle button{min-height:0;min-width:0;padding:0 6px;border-radius:0;line-height:inherit}.end-view-toggle button:first-child{padding-inline-start:0}.end-view-toggle button+button{border-inline-start:1px solid var(--wkly-text-color)}.end-view-toggle button[aria-pressed=false]{color:var(--wkly-muted-color);font-weight:400}.in-days-fields{grid-template-columns:minmax(0,1fr);gap:0;text-align:center}.resulting-end-date{font-size:11px;color:var(--wkly-muted-color);height:1.4em;margin-bottom:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.time-fields{display:grid;grid-template-columns:1fr 1fr 52px;gap:8px;padding:14px 0;border-top:1px solid var(--wkly-border-color)}.time-fields.seconds{grid-template-columns:1fr 1fr 1fr 48px}.period{display:flex;flex-direction:column;justify-content:center;gap:2px;padding-top:1.25em}.period button{font-size:.85em}.period [aria-pressed=true]{background:var(--wkly-range-color);box-shadow:inset 0 0 0 1px var(--wkly-accent-color);font-weight:700}.validation{color:var(--wkly-error-color);font-size:.85em}.validation p{margin:.5em .85em}footer{padding:12px;border-top:1px solid var(--wkly-border-color)}.confirm{background:var(--wkly-accent-color);color:var(--wkly-accent-text-color);width:100%;font-weight:650}@media (forced-colors: active){.day.selected{outline:2px solid Highlight}.range{border-bottom:2px solid Highlight}.today{outline:1px dashed CanvasText}}@media (prefers-reduced-motion: reduce){*{scroll-behavior:auto!important;animation:none!important}}\n"] }]
1276
- }], ctorParameters: function () {
1277
- return [{ type: undefined, decorators: [{
1278
- type: Inject,
1279
- args: [LOCALE_ID]
1280
- }] }, { type: undefined, decorators: [{
1281
- type: Inject,
1282
- args: [WKLY_CONFIG]
1283
- }] }, { type: undefined, decorators: [{
1284
- type: Inject,
1285
- args: [WKLY_CLOCK]
1286
- }] }, { type: undefined, decorators: [{
1287
- type: Inject,
1288
- args: [WKLY_LOCALIZATION]
1289
- }] }, { type: undefined, decorators: [{
1290
- type: Inject,
1291
- args: [WKLY_TRANSLATIONS]
1292
- }] }, { type: Object, decorators: [{
1293
- type: Inject,
1294
- args: [PLATFORM_ID]
1295
- }] }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }];
1296
- }, propDecorators: { scroller: [{
1297
- type: ViewChild,
1298
- args: ["scroller"]
1299
- }] } });
1300
-
1301
- /** Native-dialog factory. Browser resources are allocated only by open(). */
1302
- class WklyDateTimePickerDialogService {
1303
- constructor(resolver, injector, app, document, platform) {
1304
- this.resolver = resolver;
1305
- this.injector = injector;
1306
- this.app = app;
1307
- this.document = document;
1308
- this.platform = platform;
1309
- }
1310
- open(trigger, onCancel, backdrop = true, injector) {
1311
- if (!isPlatformBrowser(this.platform))
1312
- throw new Error("Picker presentations can only open in a browser");
1313
- const dialog = this.document.createElement("dialog");
1314
- dialog.setAttribute("aria-label", "Date and time picker");
1315
- Object.assign(dialog.style, {
1316
- padding: "0",
1317
- border: "0",
1318
- borderRadius: "14px",
1319
- width: "min(390px, 100vw)",
1320
- maxWidth: "100vw",
1321
- maxHeight: "94vh",
1322
- background: "transparent",
1323
- });
1324
- const component = this.resolver
1325
- .resolveComponentFactory(WklyDateTimePickerComponent)
1326
- .create(injector || this.injector);
1327
- component.instance.presentation = "transient";
1328
- dialog.appendChild(component.location.nativeElement);
1329
- this.document.body.appendChild(dialog);
1330
- this.app.attachView(component.hostView);
1331
- const cancel = (event) => {
1332
- event.preventDefault();
1333
- onCancel("escape");
1334
- };
1335
- const click = (event) => {
1336
- if (backdrop && event.target === dialog) {
1337
- const r = dialog.getBoundingClientRect();
1338
- if (event.clientX < r.left ||
1339
- event.clientX > r.right ||
1340
- event.clientY < r.top ||
1341
- event.clientY > r.bottom)
1342
- onCancel("backdrop");
1343
- }
1344
- };
1345
- const keydown = (event) => {
1346
- if (event.key !== "Tab")
1347
- return;
1348
- const controls = Array.from(dialog.querySelectorAll('button:not(:disabled),input:not(:disabled),[tabindex="0"]')).filter((el) => el.tabIndex >= 0 &&
1349
- el.getClientRects().length &&
1350
- getComputedStyle(el).visibility !== "hidden");
1351
- const first = controls[0], last = controls[controls.length - 1];
1352
- if (first &&
1353
- (event.shiftKey
1354
- ? this.document.activeElement === first
1355
- : this.document.activeElement === last)) {
1356
- event.preventDefault();
1357
- (event.shiftKey ? last : first).focus();
1358
- }
1359
- };
1360
- dialog.addEventListener("cancel", cancel);
1361
- dialog.addEventListener("click", click);
1362
- dialog.addEventListener("keydown", keydown);
1363
- dialog.showModal();
1364
- return {
1365
- component,
1366
- destroy: () => {
1367
- dialog.removeEventListener("cancel", cancel);
1368
- dialog.removeEventListener("click", click);
1369
- dialog.removeEventListener("keydown", keydown);
1370
- dialog.close();
1371
- this.app.detachView(component.hostView);
1372
- component.destroy();
1373
- dialog.remove();
1374
- trigger.focus();
1375
- },
1376
- };
1377
- }
1378
- }
1379
- WklyDateTimePickerDialogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyDateTimePickerDialogService, deps: [{ token: i0.ComponentFactoryResolver }, { token: i0.Injector }, { token: i0.ApplicationRef }, { token: DOCUMENT }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable });
1380
- WklyDateTimePickerDialogService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyDateTimePickerDialogService, providedIn: "root" });
1381
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyDateTimePickerDialogService, decorators: [{
1382
- type: Injectable,
1383
- args: [{ providedIn: "root" }]
1384
- }], ctorParameters: function () {
1385
- return [{ type: i0.ComponentFactoryResolver }, { type: i0.Injector }, { type: i0.ApplicationRef }, { type: Document, decorators: [{
1386
- type: Inject,
1387
- args: [DOCUMENT]
1388
- }] }, { type: Object, decorators: [{
1389
- type: Inject,
1390
- args: [PLATFORM_ID]
1391
- }] }];
1392
- } });
1393
- /** Shared trigger lifecycle; optional presentation packages extend this class. */
1394
- class WklyTriggerBase extends WklyPickerInputs {
1395
- constructor(element) {
1396
- super();
1397
- this.element = element;
1398
- this.ref = null;
1399
- this.subscriptions = [];
1400
- this.errors = [];
1401
- this.change = () => { };
1402
- this.touched = () => { };
1403
- this.validation = () => { };
1404
- }
1405
- open() {
1406
- if (this[WklyPickerInputsPropertyKeys.Disabled] || this.ref)
1407
- return;
1408
- this.ref = this.create();
1409
- const picker = this.ref.component.instance;
1410
- this.copy();
1411
- this.subscriptions = [
1412
- picker[WklyPickerOutputsPropertyKeys.ValueChange].subscribe((value) => {
1413
- this[WklyPickerInputsPropertyKeys.Value] = value;
1414
- this.change(value);
1415
- this[WklyPickerOutputsPropertyKeys.ValueChange].emit(value);
1416
- this.display();
1417
- }),
1418
- picker[WklyPickerOutputsPropertyKeys.ValidationChange].subscribe((errors) => {
1419
- this.errors = errors;
1420
- this[WklyPickerOutputsPropertyKeys.ValidationChange].emit(errors);
1421
- this.validation();
1422
- }),
1423
- picker[WklyPickerOutputsPropertyKeys.Closed].subscribe((reason) => this.close(reason)),
1424
- picker[WklyPickerOutputsPropertyKeys.ViewportChange].subscribe((value) => this[WklyPickerOutputsPropertyKeys.ViewportChange].emit(value)),
1425
- picker[WklyPickerOutputsPropertyKeys.ViewModeChange].subscribe((value) => this[WklyPickerOutputsPropertyKeys.ViewModeChange].emit(value)),
1426
- ];
1427
- this.ref.component.changeDetectorRef.detectChanges();
1428
- picker.focusDay();
1429
- this[WklyPickerOutputsPropertyKeys.Opened].emit();
1430
- }
1431
- key(event) {
1432
- if (event.key === "Enter" ||
1433
- event.key === " " ||
1434
- event.key === "ArrowDown") {
1435
- event.preventDefault();
1436
- this.open();
1437
- }
1438
- }
1439
- blur() {
1440
- this.touched();
1441
- }
1442
- close(reason = "programmatic") {
1443
- if (!this.ref)
1444
- return;
1445
- const ref = this.ref;
1446
- this.ref = null;
1447
- this.subscriptions.forEach((s) => s.unsubscribe());
1448
- this.subscriptions = [];
1449
- ref.destroy();
1450
- this.touched();
1451
- this[WklyPickerOutputsPropertyKeys.Closed].emit(reason);
1452
- }
1453
- ngOnChanges() {
1454
- [
1455
- WklyPickerInputsPropertyKeys.ShowSeconds,
1456
- WklyPickerInputsPropertyKeys.AllowRangeAcrossDisabled,
1457
- WklyPickerInputsPropertyKeys.Required,
1458
- WklyPickerInputsPropertyKeys.Disabled,
1459
- WklyPickerInputsPropertyKeys.CloseOnBackdrop,
1460
- ].forEach((key) => (this[key] = coerceBoolean(this[key])));
1461
- this.checkValue();
1462
- this.display();
1463
- if (this.ref) {
1464
- this.copy();
1465
- this.ref.component.instance.ngOnChanges({
1466
- [WklyPickerInputsPropertyKeys.Value]: true,
1467
- });
1468
- this.ref.component.changeDetectorRef.detectChanges();
1469
- }
1470
- }
1471
- ngOnDestroy() {
1472
- this.close();
1473
- }
1474
- copy() {
1475
- if (this.ref)
1476
- for (const name of INPUT_NAMES)
1477
- this.ref.component.instance[name] = this[name];
1478
- }
1479
- display() {
1480
- const host = this.element.nativeElement;
1481
- if (host.tagName === "INPUT") {
1482
- host.readOnly = true;
1483
- const value = this[WklyPickerInputsPropertyKeys.Value];
1484
- host.value =
1485
- value === null
1486
- ? ""
1487
- : typeof value === "string"
1488
- ? value
1489
- : value.join(" — ");
1490
- host.disabled = this[WklyPickerInputsPropertyKeys.Disabled];
1491
- host.setAttribute("aria-haspopup", "dialog");
1492
- }
1493
- }
1494
- checkValue() {
1495
- this.errors = validateSelection(this[WklyPickerInputsPropertyKeys.Value], this, this[WklyPickerInputsPropertyKeys.CalendarAdapter] ||
1496
- new WklyGregorianCalendarAdapter(this[WklyPickerInputsPropertyKeys.Locale] || "en-US"));
1497
- this[WklyPickerOutputsPropertyKeys.ValidationChange].emit(this.errors);
1498
- this.validation();
1499
- }
1500
- writeValue(value) {
1501
- this[WklyPickerInputsPropertyKeys.Value] = value;
1502
- this.checkValue();
1503
- this.display();
1504
- if (this.ref)
1505
- this.ref.component.instance.writeValue(value);
1506
- }
1507
- registerOnChange(fn) {
1508
- this.change = fn;
1509
- }
1510
- registerOnTouched(fn) {
1511
- this.touched = fn;
1512
- }
1513
- setDisabledState(value) {
1514
- this[WklyPickerInputsPropertyKeys.Disabled] = value;
1515
- this.display();
1516
- if (this.ref)
1517
- this.ref.component.instance.setDisabledState(value);
1518
- }
1519
- validate() {
1520
- return this.errors.length ? { wkly: this.errors } : null;
1521
- }
1522
- registerOnValidatorChange(fn) {
1523
- this.validation = fn;
1524
- }
1525
- scrollToEpochDay(day, options) {
1526
- var _a;
1527
- this.open();
1528
- (_a = this.ref) === null || _a === void 0 ? void 0 : _a.component.instance.scrollToEpochDay(day, options);
1529
- }
1530
- scrollToAbsoluteWeek(week, options) {
1531
- var _a;
1532
- this.open();
1533
- (_a = this.ref) === null || _a === void 0 ? void 0 : _a.component.instance.scrollToAbsoluteWeek(week, options);
1534
- }
1535
- scrollToCalendarDate(date, options) {
1536
- var _a;
1537
- this.open();
1538
- (_a = this.ref) === null || _a === void 0 ? void 0 : _a.component.instance.scrollToCalendarDate(date, options);
1539
- }
1540
- scrollToValue(value, options) {
1541
- var _a;
1542
- this.open();
1543
- (_a = this.ref) === null || _a === void 0 ? void 0 : _a.component.instance.scrollToValue(value, options);
1544
- }
1545
- }
1546
- WklyTriggerBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyTriggerBase, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
1547
- WklyTriggerBase.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: WklyTriggerBase, host: { listeners: { "click": "open()", "keydown": "key($event)", "blur": "blur()" } }, usesInheritance: true, usesOnChanges: true, ngImport: i0 });
1548
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyTriggerBase, decorators: [{
1549
- type: Directive
1550
- }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { open: [{
1551
- type: HostListener,
1552
- args: ["click"]
1553
- }], key: [{
1554
- type: HostListener,
1555
- args: ["keydown", ["$event"]]
1556
- }], blur: [{
1557
- type: HostListener,
1558
- args: ["blur"]
1559
- }] } });
1560
- class WklyDateTimePickerDialogDirective extends WklyTriggerBase {
1561
- constructor(element, service, triggerInjector) {
1562
- super(element);
1563
- this.service = service;
1564
- this.triggerInjector = triggerInjector;
1565
- }
1566
- create() {
1567
- return this.service.open(this.element.nativeElement, (reason) => this.close(reason), this[WklyPickerInputsPropertyKeys.CloseOnBackdrop], this.triggerInjector);
1568
- }
1569
- }
1570
- WklyDateTimePickerDialogDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyDateTimePickerDialogDirective, deps: [{ token: i0.ElementRef }, { token: WklyDateTimePickerDialogService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Directive });
1571
- WklyDateTimePickerDialogDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.10", type: WklyDateTimePickerDialogDirective, selector: "[wklyDateTimePickerDialog]", providers: [
1572
- {
1573
- provide: NG_VALUE_ACCESSOR,
1574
- useExisting: forwardRef(() => WklyDateTimePickerDialogDirective),
1575
- multi: true,
1576
- },
1577
- {
1578
- provide: NG_VALIDATORS,
1579
- useExisting: forwardRef(() => WklyDateTimePickerDialogDirective),
1580
- multi: true,
1581
- },
1582
- ], exportAs: ["wklyDialog"], usesInheritance: true, ngImport: i0 });
1583
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyDateTimePickerDialogDirective, decorators: [{
1584
- type: Directive,
1585
- args: [{
1586
- selector: "[wklyDateTimePickerDialog]",
1587
- exportAs: "wklyDialog",
1588
- providers: [
1589
- {
1590
- provide: NG_VALUE_ACCESSOR,
1591
- useExisting: forwardRef(() => WklyDateTimePickerDialogDirective),
1592
- multi: true,
1593
- },
1594
- {
1595
- provide: NG_VALIDATORS,
1596
- useExisting: forwardRef(() => WklyDateTimePickerDialogDirective),
1597
- multi: true,
1598
- },
1599
- ],
1600
- }]
1601
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: WklyDateTimePickerDialogService }, { type: i0.Injector }]; } });
1602
-
1603
- class WklyDateTimePickerModule {
1604
- }
1605
- WklyDateTimePickerModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyDateTimePickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1606
- WklyDateTimePickerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.10", ngImport: i0, type: WklyDateTimePickerModule, declarations: [WklyDateTimePickerComponent,
1607
- WklyDateTimePickerDialogDirective,
1608
- WklyFieldComponent], imports: [CommonModule], exports: [WklyDateTimePickerComponent, WklyDateTimePickerDialogDirective] });
1609
- WklyDateTimePickerModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyDateTimePickerModule, imports: [CommonModule] });
1610
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: WklyDateTimePickerModule, decorators: [{
1611
- type: NgModule,
1612
- args: [{
1613
- imports: [CommonModule],
1614
- declarations: [
1615
- WklyDateTimePickerComponent,
1616
- WklyDateTimePickerDialogDirective,
1617
- WklyFieldComponent,
1618
- ],
1619
- entryComponents: [WklyDateTimePickerComponent],
1620
- exports: [WklyDateTimePickerComponent, WklyDateTimePickerDialogDirective],
1621
- }]
1622
- }] });
1623
-
1624
- /**
1625
- * Generated bundle index. Do not edit.
1626
- */
1627
-
1628
- export { WKLY_CLOCK, WKLY_CONFIG, WKLY_LOCALIZATION, WKLY_TRANSLATIONS, WklyDateTimePickerComponent, WklyDateTimePickerDialogDirective, WklyDateTimePickerDialogService, WklyDateTimePickerModule, WklyFieldComponent, WklyPickerInputs, WklyTriggerBase };
1629
- //# sourceMappingURL=wkly-datetime-picker.mjs.map