@wkly/datetime-picker 14.0.0 → 16.0.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,1624 +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: "14.3.0", ngImport: i0, type: WklyPickerInputs, deps: [], target: i0.ɵɵFactoryTarget.Directive });
62
- WklyPickerInputs.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.3.0", 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: "14.3.0", 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: "14.3.0", ngImport: i0, type: WklyFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
321
- WklyFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", 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}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: "14.3.0", 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}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
- this.effectiveHourCycle =
523
- this[WklyPickerInputsPropertyKeys.HourCycle] === "h12"
524
- ? "h12"
525
- : this[WklyPickerInputsPropertyKeys.HourCycle] === "locale"
526
- ? new Intl.DateTimeFormat(this.effectiveLocale, {
527
- hour: "numeric",
528
- timeZone: "UTC",
529
- }).resolvedOptions().hour12
530
- ? "h12"
531
- : "h24"
532
- : "h24";
533
- this.weekdays = Array.from({ length: 7 }, (_, i) => this.adapter.formatWeekday(this.effectiveOffset + i, "short"));
534
- }
535
- setSupportedScrollRange() {
536
- let [first, last] = this.adapter.supportedEpochDayRange;
537
- const [firstYear, lastYear] = this.adapter.supportedYearRange;
538
- const yearOf = (day) => this.adapter.epochDayToDate(day).year;
539
- if (yearOf(first) < firstYear) {
540
- let low = first, high = last;
541
- while (low < high) {
542
- const mid = Math.floor((low + high) / 2);
543
- if (yearOf(mid) < firstYear)
544
- low = mid + 1;
545
- else
546
- high = mid;
547
- }
548
- first = low;
549
- }
550
- if (yearOf(last) > lastYear) {
551
- let low = first, high = last;
552
- while (low < high) {
553
- const mid = Math.ceil((low + high) / 2);
554
- if (yearOf(mid) > lastYear)
555
- high = mid - 1;
556
- else
557
- low = mid;
558
- }
559
- last = low;
560
- }
561
- if (first > last ||
562
- yearOf(first) < firstYear ||
563
- yearOf(first) > lastYear ||
564
- yearOf(last) < firstYear ||
565
- yearOf(last) > lastYear)
566
- throw new RangeError("No supported days within the calendar year range");
567
- this.firstSupportedDay = first;
568
- this.lastSupportedDay = last;
569
- this.firstSupportedWeek = absoluteWeekOf(first, this.effectiveOffset);
570
- this.lastSupportedWeek = absoluteWeekOf(last, this.effectiveOffset);
571
- }
572
- clampFirstWeek(week) {
573
- // Keep supported weeks inside the viewport; renderRows adds the buffer rows.
574
- const last = Math.max(this.firstSupportedWeek, this.lastSupportedWeek - this.visibleCount + 1);
575
- return Math.max(this.firstSupportedWeek, Math.min(last, week));
576
- }
577
- ngAfterViewInit() {
578
- this.resetScroll();
579
- if (this.browser && typeof ResizeObserver !== "undefined") {
580
- this.observer = new ResizeObserver(() => {
581
- this.compact = this.host.nativeElement.clientWidth < 338;
582
- const row = this.host.nativeElement.querySelector(".week-row");
583
- // CSS heights and scrollTop use layout pixels; client rectangles include zoom.
584
- const height = row ? parseFloat(getComputedStyle(row).height) : 0;
585
- if (height && height !== this.rowHeight) {
586
- this.rowHeight = height;
587
- this.scrollHeight = this.rowHeight * 2001;
588
- this.renderRows();
589
- this.resetScroll();
590
- }
591
- });
592
- this.observer.observe(this.host.nativeElement);
593
- }
594
- }
595
- ngOnDestroy() {
596
- this.destroyed = true;
597
- if (this.observer)
598
- this.observer.disconnect();
599
- if (this.scrollEndTimer)
600
- clearTimeout(this.scrollEndTimer);
601
- if (this.generator)
602
- this.generator.clearCache();
603
- }
604
- t(key) {
605
- return resolveWklyTranslation(key, this.effectiveLocale, this[WklyPickerInputsPropertyKeys.Translations] ||
606
- this.defaultTranslations, this.strings);
607
- }
608
- get isRange() {
609
- return this[WklyPickerInputsPropertyKeys.Mode].endsWith("-range");
610
- }
611
- get hasDate() {
612
- return !this[WklyPickerInputsPropertyKeys.Mode].startsWith("time");
613
- }
614
- get hasTime() {
615
- return (this[WklyPickerInputsPropertyKeys.Mode] !== "date" &&
616
- this[WklyPickerInputsPropertyKeys.Mode] !== "date-range");
617
- }
618
- get submitVisible() {
619
- return (this.presentation === "transient" &&
620
- (this[WklyPickerInputsPropertyKeys.Mode] !== "date" ||
621
- this.viewMode === "manual"));
622
- }
623
- get title() {
624
- try {
625
- const d = this.adapter.epochDayToDate(Math.max(this.firstSupportedDay, Math.min(this.lastSupportedDay, firstEpochDayOf(this.anchorWeek, this.effectiveOffset))));
626
- return this.adapter.formatMonth(d) + " " + this.adapter.formatYear(d);
627
- }
628
- catch (_) {
629
- return "";
630
- }
631
- }
632
- get canSubmit() {
633
- return (!this[WklyPickerInputsPropertyKeys.Disabled] &&
634
- !this.errors.length &&
635
- this.pendingValue !== null);
636
- }
637
- blank(day) {
638
- const safe = Math.max(this.firstSupportedDay, Math.min(this.lastSupportedDay, day));
639
- return {
640
- date: this.adapter.epochDayToDate(safe),
641
- hour: 0,
642
- minute: 0,
643
- second: 0,
644
- present: false,
645
- };
646
- }
647
- load(value) {
648
- this.drafts = [this.blank(this.focused), this.blank(this.focused)];
649
- const validation = validateSelection(value, this, this.adapter);
650
- if (value !== null && !validation.length) {
651
- const values = typeof value === "string" ? [value] : value;
652
- values.forEach((v, i) => {
653
- const d = decodeIso(v);
654
- this.drafts[i] = {
655
- date: this.hasDate
656
- ? this.adapter.epochDayToDate(d.epochDay)
657
- : this.blank(this.today).date,
658
- hour: d.hour,
659
- minute: d.minute,
660
- second: d.second,
661
- present: true,
662
- };
663
- if (i === 0 && this.hasDate)
664
- this.focused = d.epochDay;
665
- });
666
- }
667
- if (validation.length) {
668
- this.pendingValue = null;
669
- this.report(validation);
670
- }
671
- else
672
- this.check();
673
- }
674
- writeValue(value) {
675
- this[WklyPickerInputsPropertyKeys.Value] = value;
676
- if (this.initialized) {
677
- this.load(value);
678
- this.position(this.focused, true);
679
- }
680
- }
681
- registerOnChange(fn) {
682
- this.onChange = fn;
683
- }
684
- registerOnTouched(fn) {
685
- this.onTouched = fn;
686
- }
687
- setDisabledState(disabled) {
688
- this[WklyPickerInputsPropertyKeys.Disabled] = disabled;
689
- }
690
- validate(_control) {
691
- return this.errors.length ? { wkly: this.errors } : null;
692
- }
693
- registerOnValidatorChange(fn) {
694
- this.validatorChanged = fn;
695
- }
696
- touched() {
697
- Promise.resolve().then(() => this.onTouched());
698
- }
699
- report(errors) {
700
- const changed = JSON.stringify(this.errors) !== JSON.stringify(errors);
701
- this.errors = errors;
702
- if (changed) {
703
- this[WklyPickerOutputsPropertyKeys.ValidationChange].emit(errors);
704
- this.validatorChanged();
705
- }
706
- }
707
- check() {
708
- const result = validateDrafts({
709
- drafts: this.drafts,
710
- configErrors: this.configErrors,
711
- adapter: this.adapter,
712
- selection: this,
713
- mode: this[WklyPickerInputsPropertyKeys.Mode],
714
- isRange: this.isRange,
715
- hasDate: this.hasDate,
716
- hasTime: this.hasTime,
717
- showSeconds: this[WklyPickerInputsPropertyKeys.ShowSeconds],
718
- required: this[WklyPickerInputsPropertyKeys.Required],
719
- });
720
- this.pendingValue = result.pendingValue;
721
- this.report(result.errors);
722
- }
723
- trackDraft(index) {
724
- // Endpoint controls keep their identity and focus when draft objects swap.
725
- return index;
726
- }
727
- orderDrafts() {
728
- if (!this.isRange || !this.drafts.every((draft) => draft.present))
729
- return;
730
- if (this.drafts.some((draft) => draft.unsupportedEpochDay !== undefined))
731
- return;
732
- try {
733
- const a = this.drafts[0], b = this.drafts[1];
734
- const key = (d) => this.adapter.dateToEpochDay(d.date) * 86400 +
735
- (d.hour || 0) * 3600 +
736
- (d.minute || 0) * 60 +
737
- (d.second || 0);
738
- if (key(a) > key(b))
739
- this.drafts = [b, a];
740
- }
741
- catch (_) {
742
- // Impossible or incomplete dates remain editable until corrected.
743
- }
744
- }
745
- finish() {
746
- if (this[WklyPickerInputsPropertyKeys.Disabled])
747
- return;
748
- this.orderDrafts();
749
- if (this.viewMode === "manual" && this.hasDate)
750
- this.positionOnManualDate();
751
- this.check();
752
- if (this.presentation === "inline" && this.canSubmit)
753
- this.commit();
754
- }
755
- commit() {
756
- if (!this.canSubmit)
757
- return;
758
- const next = this.pendingValue;
759
- if (JSON.stringify(next) !==
760
- JSON.stringify(this[WklyPickerInputsPropertyKeys.Value])) {
761
- this[WklyPickerInputsPropertyKeys.Value] = next;
762
- this.emittedValue = JSON.stringify(next);
763
- this.onChange(next);
764
- this[WklyPickerOutputsPropertyKeys.ValueChange].emit(next);
765
- }
766
- this.onTouched();
767
- }
768
- submit(reason = "submit") {
769
- this.check();
770
- if (!this.canSubmit)
771
- return;
772
- this.commit();
773
- if (this.presentation === "transient")
774
- this[WklyPickerOutputsPropertyKeys.Closed].emit(reason);
775
- }
776
- cancel(reason = "close-button") {
777
- if (this[WklyPickerInputsPropertyKeys.Disabled])
778
- return;
779
- this.load(this[WklyPickerInputsPropertyKeys.Value]);
780
- this.onTouched();
781
- this[WklyPickerOutputsPropertyKeys.Closed].emit(reason);
782
- }
783
- now() {
784
- if (this[WklyPickerInputsPropertyKeys.Disabled])
785
- return;
786
- const n = this.clock.now();
787
- const day = Math.floor(n.getTime() / 86400000);
788
- this.drafts = [0, 1].map((index) => (Object.assign(Object.assign({}, this.clockDraft(day, n)), { present: index === 0 || this.isRange })));
789
- if (this.hasDate &&
790
- (day < this.firstSupportedDay || day > this.lastSupportedDay)) {
791
- this.report([error("unsupported-adapter-date", day)]);
792
- return;
793
- }
794
- this.focused = day;
795
- this.position(day, true);
796
- this.check();
797
- this.submit("now");
798
- }
799
- clockDraft(day, now) {
800
- 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]
801
- ? Math.floor(now.getUTCSeconds() / this[WklyPickerInputsPropertyKeys.SecondStep]) * this[WklyPickerInputsPropertyKeys.SecondStep]
802
- : 0 });
803
- }
804
- initializeManualRange() {
805
- if (!this.isRange ||
806
- !this.hasDate ||
807
- this.drafts.every((draft) => draft.present))
808
- return;
809
- let seed = this.drafts.find((draft) => draft.present);
810
- if (!seed) {
811
- if (this[WklyPickerInputsPropertyKeys.Value] !== null)
812
- return;
813
- const now = this.clock.now();
814
- const initialEpochDay = this[WklyPickerInputsPropertyKeys.InitialEpochDay];
815
- const day = initialEpochDay === null
816
- ? this.defaults.initialEpochDay === undefined
817
- ? Math.floor(now.getTime() / 86400000)
818
- : this.defaults.initialEpochDay
819
- : initialEpochDay;
820
- seed = Object.assign(Object.assign({}, this.clockDraft(day, now)), { present: true });
821
- }
822
- // Complete missing endpoints without replacing selected or invalid drafts.
823
- const initial = seed;
824
- this.drafts = this.drafts.map((draft) => draft.present ? draft : Object.assign(Object.assign({}, initial), { date: Object.assign({}, initial.date) }));
825
- this.finish();
826
- // Positioning renders before validation; refresh completion controls afterward.
827
- this.changeDetector.markForCheck();
828
- }
829
- toggleView() {
830
- if (this[WklyPickerInputsPropertyKeys.Disabled] || !this.hasDate)
831
- return;
832
- this.viewMode = this.viewMode === "calendar" ? "manual" : "calendar";
833
- if (this.viewMode === "manual")
834
- this.initializeManualRange();
835
- if (this.viewMode === "calendar")
836
- this.positionOnManualDate();
837
- this[WklyPickerOutputsPropertyKeys.ViewModeChange].emit(this.viewMode);
838
- if (this.viewMode === "calendar")
839
- setTimeout(() => this.resetScroll());
840
- }
841
- positionOnManualDate() {
842
- const draft = this.drafts[this.manualDateEndpoint];
843
- if (!draft || !draft.present)
844
- return;
845
- try {
846
- // A valid day follows the selection. An impossible day keeps its draft
847
- // fields but still shows the chosen month in the calendar.
848
- const target = this.adapter.dateToEpochDay(draft.date);
849
- this.focused = target;
850
- this.position(target, true);
851
- }
852
- catch (_) {
853
- try {
854
- const first = this.adapter.dateToEpochDay(Object.assign(Object.assign({}, draft.date), { day: 1 }));
855
- this.focused = first;
856
- this.position(first, true);
857
- }
858
- catch (_) { }
859
- }
860
- }
861
- months(draft) {
862
- try {
863
- return this.adapter.getMonths(draft.date.year).map((m) => m.label);
864
- }
865
- catch (_) {
866
- return [];
867
- }
868
- }
869
- monthCount(draft) {
870
- return this.months(draft).length || 12;
871
- }
872
- get inDays() {
873
- return draftDayDifference(this.drafts, this.adapter);
874
- }
875
- get inDaysLabel() {
876
- const days = this.inDays;
877
- return this.t("inDays").replace(/{{\s*days\s*}}/g, days === null
878
- ? this.t("daysUnavailable")
879
- : new Intl.NumberFormat(this.effectiveLocale, {
880
- useGrouping: false,
881
- }).format(days));
882
- }
883
- get resultingEndDate() {
884
- try {
885
- const draft = this.drafts[1];
886
- if (draft.unsupportedEpochDay !== undefined ||
887
- this.adapter.validateDate(draft.date).length)
888
- return "";
889
- return [
890
- this.adapter.formatDay(draft.date),
891
- this.adapter.formatMonth(draft.date),
892
- this.adapter.formatYear(draft.date),
893
- ].join(" ");
894
- }
895
- catch (_) {
896
- return "";
897
- }
898
- }
899
- toggleEndView(view) {
900
- if (this[WklyPickerInputsPropertyKeys.Disabled])
901
- return;
902
- this.endView = view;
903
- }
904
- days(value) {
905
- if (this[WklyPickerInputsPropertyKeys.Disabled])
906
- return;
907
- this.manualDateEndpoint = 1;
908
- setDraftDayDifference(this.drafts, this.adapter, value);
909
- this.check();
910
- }
911
- field(index, field, value) {
912
- if (this[WklyPickerInputsPropertyKeys.Disabled])
913
- return;
914
- const draft = this.drafts[index];
915
- draft.present = true;
916
- if (field === "day" || field === "year" || field === "month") {
917
- this.manualDateEndpoint = index;
918
- delete draft.unsupportedEpochDay;
919
- let date = Object.assign(Object.assign({}, draft.date), { [field]: value });
920
- if (field === "month") {
921
- let month;
922
- try {
923
- month = this.adapter
924
- .getMonths(date.year)
925
- .find((m) => m.month === value);
926
- }
927
- catch (_) { }
928
- date = Object.assign(Object.assign({}, date), { monthCode: month ? month.monthCode : "" });
929
- }
930
- if (field === "year" && value !== null) {
931
- try {
932
- const months = this.adapter.getMonths(value);
933
- const month = months.find((m) => m.monthCode === date.monthCode);
934
- if (month)
935
- date = Object.assign(Object.assign({}, date), { month: month.month });
936
- }
937
- catch (_) { }
938
- }
939
- draft.date = date;
940
- }
941
- else if (field === "hour" && this.effectiveHourCycle === "h12")
942
- draft.hour =
943
- value === null
944
- ? null
945
- : value >= 1 && value <= 12
946
- ? (value % 12) + ((draft.hour || 0) >= 12 ? 12 : 0)
947
- : 24 + value;
948
- else
949
- draft[field] = value;
950
- this.check();
951
- }
952
- displayHour(draft) {
953
- return draft.hour === null
954
- ? null
955
- : this.effectiveHourCycle === "h12"
956
- ? draft.hour % 12 || 12
957
- : draft.hour;
958
- }
959
- period(index, period) {
960
- if (this[WklyPickerInputsPropertyKeys.Disabled])
961
- return;
962
- if (period === "24")
963
- this.effectiveHourCycle = "h24";
964
- else {
965
- this.effectiveHourCycle = "h12";
966
- this.drafts[index].hour =
967
- ((this.drafts[index].hour || 0) % 12) + (period === "pm" ? 12 : 0);
968
- this.drafts[index].present = true;
969
- this.finish();
970
- }
971
- }
972
- selected(day) {
973
- return this.drafts.some((d) => {
974
- try {
975
- return d.present && this.adapter.dateToEpochDay(d.date) === day;
976
- }
977
- catch (_) {
978
- return false;
979
- }
980
- });
981
- }
982
- inRange(day) {
983
- if (!this.isRange || !this.drafts.every((d) => d.present))
984
- return false;
985
- try {
986
- const a = this.adapter.dateToEpochDay(this.drafts[0].date), b = this.adapter.dateToEpochDay(this.drafts[1].date);
987
- return day > Math.min(a, b) && day < Math.max(a, b);
988
- }
989
- catch (_) {
990
- return false;
991
- }
992
- }
993
- dayDisabled(day) {
994
- var _a, _b;
995
- if (day < this.firstSupportedDay || day > this.lastSupportedDay)
996
- return true;
997
- try {
998
- const date = this.adapter.epochDayToDate(day);
999
- const isDateDisabled = this[WklyPickerInputsPropertyKeys.IsDateDisabled];
1000
- if (isDateDisabled &&
1001
- isDateDisabled(day, {
1002
- mode: this[WklyPickerInputsPropertyKeys.Mode],
1003
- endpoint: this.isRange
1004
- ? ((_a = this.drafts[0]) === null || _a === void 0 ? void 0 : _a.present) && !((_b = this.drafts[1]) === null || _b === void 0 ? void 0 : _b.present)
1005
- ? "end"
1006
- : "start"
1007
- : "single",
1008
- calendarDate: date,
1009
- }))
1010
- return true;
1011
- const min = this[WklyPickerInputsPropertyKeys.Min];
1012
- const max = this[WklyPickerInputsPropertyKeys.Max];
1013
- if (min && day < decodeIso(min).epochDay)
1014
- return true;
1015
- if (max && day > decodeIso(max).epochDay)
1016
- return true;
1017
- return false;
1018
- }
1019
- catch (_) {
1020
- return true;
1021
- }
1022
- }
1023
- select(day) {
1024
- if (this[WklyPickerInputsPropertyKeys.Disabled] || this.dayDisabled(day))
1025
- return;
1026
- this.focused = day;
1027
- const index = this.isRange && this.drafts[0].present && !this.drafts[1].present ? 1 : 0;
1028
- if (this.isRange && index === 0)
1029
- this.drafts[1].present = false;
1030
- delete this.drafts[index].unsupportedEpochDay;
1031
- this.drafts[index].date = this.adapter.epochDayToDate(day);
1032
- this.drafts[index].present = true;
1033
- this.orderDrafts();
1034
- this.renderRows();
1035
- this.finish();
1036
- if (this.presentation === "transient" &&
1037
- this[WklyPickerInputsPropertyKeys.Mode] === "date" &&
1038
- this.viewMode === "calendar")
1039
- this.submit("auto-submit");
1040
- }
1041
- key(event, day) {
1042
- let delta = 0;
1043
- if (event.key === "ArrowLeft")
1044
- delta = -1;
1045
- if (event.key === "ArrowRight")
1046
- delta = 1;
1047
- if (event.key === "ArrowUp")
1048
- delta = -7;
1049
- if (event.key === "ArrowDown")
1050
- delta = 7;
1051
- if (event.key === "PageUp")
1052
- delta = -7 * (event.shiftKey ? this.visibleCount : 1);
1053
- if (event.key === "PageDown")
1054
- delta = 7 * (event.shiftKey ? this.visibleCount : 1);
1055
- if (event.key === "Home") {
1056
- event.preventDefault();
1057
- this.scrollToEpochDay(this.today, { focus: true });
1058
- }
1059
- if (delta) {
1060
- event.preventDefault();
1061
- const target = day + delta;
1062
- if (target >= this.firstSupportedDay && target <= this.lastSupportedDay)
1063
- this.scrollToEpochDay(target, { focus: true });
1064
- }
1065
- }
1066
- position(day, preset = false, options = {}) {
1067
- day = Math.max(this.firstSupportedDay, Math.min(this.lastSupportedDay, day));
1068
- this.anchorWeek = absoluteWeekOf(day, this.effectiveOffset);
1069
- const viewportPreset = this[WklyPickerInputsPropertyKeys.ViewportPreset];
1070
- this.clipMonth = preset && viewportPreset.kind === "full-month";
1071
- if (preset && viewportPreset.kind !== "weeks") {
1072
- const d = this.adapter.epochDayToDate(day);
1073
- this.initialMonth = d.year + "/" + d.monthCode;
1074
- const [start, end] = calendarMonthBounds(this.adapter, day);
1075
- this.firstWeek = absoluteWeekOf(start, this.effectiveOffset);
1076
- this.visibleCount =
1077
- absoluteWeekOf(end, this.effectiveOffset) - this.firstWeek + 1;
1078
- if (viewportPreset.kind === "full-month-and-around" &&
1079
- !this.configErrors.length) {
1080
- const before = viewportPreset.extraWeeksBefore || 0, after = viewportPreset.extraWeeksAfter || 0;
1081
- this.firstWeek -= before;
1082
- this.visibleCount += before + after;
1083
- }
1084
- }
1085
- else {
1086
- if (viewportPreset.kind === "weeks")
1087
- this.visibleCount = this.configErrors.length
1088
- ? 6
1089
- : viewportPreset.visibleWeekCount;
1090
- this.firstWeek =
1091
- this.anchorWeek -
1092
- (options.align === "start"
1093
- ? 0
1094
- : options.align === "end"
1095
- ? this.visibleCount - 1
1096
- : Math.floor(this.visibleCount / 2));
1097
- }
1098
- this.firstWeek = this.clampFirstWeek(this.firstWeek);
1099
- this.baseWeek = this.firstWeek - 1000;
1100
- this.renderRows();
1101
- // Apply the new runway before writing scrollTop or locating a focus target.
1102
- this.changeDetector.detectChanges();
1103
- this.resetScroll();
1104
- }
1105
- resetScroll() {
1106
- // Round week boundaries to avoid scrollTop truncation under CSS zoom.
1107
- if (this.scroller)
1108
- this.scroller.nativeElement.scrollTop = Math.round(1000 * this.rowHeight);
1109
- }
1110
- scroll(event) {
1111
- const element = event.target;
1112
- this.snapPending = true;
1113
- this.scheduleSnap();
1114
- // Quantize displacement around the reset point, equally in both directions.
1115
- const relativeRows = element.scrollTop / this.rowHeight - 1000;
1116
- const index = 1000 + Math.sign(relativeRows) * Math.round(Math.abs(relativeRows));
1117
- const requestedFirst = this.baseWeek + index;
1118
- const first = this.clampFirstWeek(requestedFirst);
1119
- if (requestedFirst !== first) {
1120
- element.scrollTop = Math.round((first - this.baseWeek) * this.rowHeight);
1121
- }
1122
- if (first === this.firstWeek)
1123
- return;
1124
- this.clipMonth = false;
1125
- this.firstWeek = first;
1126
- this.anchorWeek = first + Math.floor(this.visibleCount / 2);
1127
- if (index < 100 || index > 1900) {
1128
- // Preserve signed displacement from this week; modulo turns fractional
1129
- // rounding just below a boundary into almost a full row after rebasing.
1130
- const offset = element.scrollTop - (first - this.baseWeek) * this.rowHeight;
1131
- this.baseWeek = first - 1000;
1132
- element.scrollTop = Math.round(1000 * this.rowHeight + offset);
1133
- }
1134
- this.renderRows();
1135
- }
1136
- scheduleSnap() {
1137
- if (this.scrollEndTimer)
1138
- clearTimeout(this.scrollEndTimer);
1139
- this.scrollEndTimer = setTimeout(() => this.snapWeek(), 200);
1140
- }
1141
- snapWeek() {
1142
- if (this.scrollEndTimer)
1143
- clearTimeout(this.scrollEndTimer);
1144
- this.scrollEndTimer = undefined;
1145
- if (!this.snapPending || !this.scroller)
1146
- return;
1147
- this.snapPending = false;
1148
- // Align the current virtual week without rebuilding or rebasing its rows.
1149
- const element = this.scroller.nativeElement;
1150
- const target = Math.round((this.firstWeek - this.baseWeek) * this.rowHeight);
1151
- if (element.scrollTop !== target)
1152
- element.scrollTop = target;
1153
- }
1154
- showFirstWeek(week) {
1155
- const first = this.clampFirstWeek(week);
1156
- if (first === this.firstWeek)
1157
- return;
1158
- this.clipMonth = false;
1159
- this.firstWeek = first;
1160
- this.anchorWeek = first + Math.floor(this.visibleCount / 2);
1161
- this.baseWeek = first - 1000;
1162
- this.renderRows();
1163
- this.resetScroll();
1164
- }
1165
- canMoveWeek(delta) {
1166
- return this.clampFirstWeek(this.firstWeek + delta) !== this.firstWeek;
1167
- }
1168
- moveWeek(delta) {
1169
- if (!this[WklyPickerInputsPropertyKeys.Disabled])
1170
- this.showFirstWeek(this.firstWeek + delta);
1171
- }
1172
- renderRows() {
1173
- // Keep the virtual scroll offset here; row data is shared across Angular versions.
1174
- const overscan = Math.max(0, Math.min(50, this[WklyPickerInputsPropertyKeys.OverscanWeeks] || 0));
1175
- const start = this.firstWeek - overscan;
1176
- this.paddingTop = (start - this.baseWeek) * this.rowHeight;
1177
- this.rows = createWeekRows({
1178
- generator: this.generator,
1179
- adapter: this.adapter,
1180
- startWeek: start,
1181
- count: this.visibleCount + 2 * overscan,
1182
- firstVisibleWeek: this.firstWeek,
1183
- firstSupportedDay: this.firstSupportedDay,
1184
- lastSupportedDay: this.lastSupportedDay,
1185
- clipMonth: this.clipMonth,
1186
- initialMonth: this.initialMonth,
1187
- weekLabelMode: this[WklyPickerInputsPropertyKeys.WeekLabelMode],
1188
- weekLabelFormatter: this[WklyPickerInputsPropertyKeys.WeekLabelFormatter] || null,
1189
- isDayDisabled: (day) => this.dayDisabled(day),
1190
- });
1191
- this[WklyPickerOutputsPropertyKeys.ViewportChange].emit({
1192
- firstVisibleAbsoluteWeek: this.firstWeek,
1193
- lastVisibleAbsoluteWeek: this.firstWeek + this.visibleCount - 1,
1194
- anchorAbsoluteWeek: this.anchorWeek,
1195
- });
1196
- }
1197
- // Retain day DOM nodes and keyboard focus when row metadata is regenerated.
1198
- trackCell(_i, cell) {
1199
- return cell.epochDay;
1200
- }
1201
- trackRow(_i, row) {
1202
- return row.week.absoluteWeek;
1203
- }
1204
- scrollToEpochDay(day, options = {}) {
1205
- integer(day);
1206
- this.adapter.epochDayToDate(day);
1207
- day = Math.max(this.firstSupportedDay, Math.min(this.lastSupportedDay, day));
1208
- // position renders synchronously; publish the tab stop before that render.
1209
- if (options.focus)
1210
- this.focused = day;
1211
- this.position(day, false, options);
1212
- if (options.select)
1213
- this.select(day);
1214
- if (options.focus)
1215
- this.focusDay();
1216
- }
1217
- scrollToAbsoluteWeek(week, options = {}) {
1218
- // A boundary week can start before the adapter's first supported day.
1219
- const first = firstEpochDayOf(week, this.effectiveOffset);
1220
- this.scrollToEpochDay(week === this.firstSupportedWeek
1221
- ? Math.max(first, this.firstSupportedDay)
1222
- : first, options);
1223
- }
1224
- scrollToCalendarDate(date, options = {}) {
1225
- this.scrollToEpochDay(this.adapter.dateToEpochDay(date), options);
1226
- }
1227
- scrollToValue(value, options = {}) {
1228
- this.scrollToEpochDay(decodeIso(value).epochDay, options);
1229
- }
1230
- focusDay() {
1231
- if (!this.browser)
1232
- return;
1233
- setTimeout(() => {
1234
- var _a;
1235
- if (this.destroyed)
1236
- return;
1237
- this.changeDetector.detectChanges();
1238
- const day = this.host.nativeElement.querySelector('[data-day="' + this.focused + '"]');
1239
- const fallback = this.host.nativeElement.querySelector("button:not(:disabled),input:not(:disabled)");
1240
- (_a = (day || fallback)) === null || _a === void 0 ? void 0 : _a.focus({ preventScroll: true });
1241
- });
1242
- }
1243
- }
1244
- WklyDateTimePickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", 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 });
1245
- WklyDateTimePickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: WklyDateTimePickerComponent, selector: "wkly-datetime-picker", providers: [
1246
- {
1247
- provide: NG_VALUE_ACCESSOR,
1248
- useExisting: forwardRef(() => WklyDateTimePickerComponent),
1249
- multi: true,
1250
- },
1251
- {
1252
- provide: NG_VALIDATORS,
1253
- useExisting: forwardRef(() => WklyDateTimePickerComponent),
1254
- multi: true,
1255
- },
1256
- ], 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}button:hover:not(:disabled):not([aria-disabled=\"true\"]){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}.confirm:hover:not(:disabled){background:var(--wkly-accent-color-alternate)}@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"] }] });
1257
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WklyDateTimePickerComponent, decorators: [{
1258
- type: Component,
1259
- args: [{ selector: "wkly-datetime-picker", providers: [
1260
- {
1261
- provide: NG_VALUE_ACCESSOR,
1262
- useExisting: forwardRef(() => WklyDateTimePickerComponent),
1263
- multi: true,
1264
- },
1265
- {
1266
- provide: NG_VALIDATORS,
1267
- useExisting: forwardRef(() => WklyDateTimePickerComponent),
1268
- multi: true,
1269
- },
1270
- ], 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}button:hover:not(:disabled):not([aria-disabled=\"true\"]){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}.confirm:hover:not(:disabled){background:var(--wkly-accent-color-alternate)}@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"] }]
1271
- }], ctorParameters: function () {
1272
- return [{ type: undefined, decorators: [{
1273
- type: Inject,
1274
- args: [LOCALE_ID]
1275
- }] }, { type: undefined, decorators: [{
1276
- type: Inject,
1277
- args: [WKLY_CONFIG]
1278
- }] }, { type: undefined, decorators: [{
1279
- type: Inject,
1280
- args: [WKLY_CLOCK]
1281
- }] }, { type: undefined, decorators: [{
1282
- type: Inject,
1283
- args: [WKLY_LOCALIZATION]
1284
- }] }, { type: undefined, decorators: [{
1285
- type: Inject,
1286
- args: [WKLY_TRANSLATIONS]
1287
- }] }, { type: Object, decorators: [{
1288
- type: Inject,
1289
- args: [PLATFORM_ID]
1290
- }] }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }];
1291
- }, propDecorators: { scroller: [{
1292
- type: ViewChild,
1293
- args: ["scroller"]
1294
- }] } });
1295
-
1296
- /** Native-dialog factory. Browser resources are allocated only by open(). */
1297
- class WklyDateTimePickerDialogService {
1298
- constructor(resolver, injector, app, document, platform) {
1299
- this.resolver = resolver;
1300
- this.injector = injector;
1301
- this.app = app;
1302
- this.document = document;
1303
- this.platform = platform;
1304
- }
1305
- open(trigger, onCancel, backdrop = true, injector) {
1306
- if (!isPlatformBrowser(this.platform))
1307
- throw new Error("Picker presentations can only open in a browser");
1308
- const dialog = this.document.createElement("dialog");
1309
- dialog.setAttribute("aria-label", "Date and time picker");
1310
- Object.assign(dialog.style, {
1311
- padding: "0",
1312
- border: "0",
1313
- borderRadius: "14px",
1314
- width: "min(390px, 100vw)",
1315
- maxWidth: "100vw",
1316
- maxHeight: "94vh",
1317
- background: "transparent",
1318
- });
1319
- const component = this.resolver
1320
- .resolveComponentFactory(WklyDateTimePickerComponent)
1321
- .create(injector || this.injector);
1322
- component.instance.presentation = "transient";
1323
- dialog.appendChild(component.location.nativeElement);
1324
- this.document.body.appendChild(dialog);
1325
- this.app.attachView(component.hostView);
1326
- const cancel = (event) => {
1327
- event.preventDefault();
1328
- onCancel("escape");
1329
- };
1330
- const click = (event) => {
1331
- if (backdrop && event.target === dialog) {
1332
- const r = dialog.getBoundingClientRect();
1333
- if (event.clientX < r.left ||
1334
- event.clientX > r.right ||
1335
- event.clientY < r.top ||
1336
- event.clientY > r.bottom)
1337
- onCancel("backdrop");
1338
- }
1339
- };
1340
- const keydown = (event) => {
1341
- if (event.key !== "Tab")
1342
- return;
1343
- const controls = Array.from(dialog.querySelectorAll('button:not(:disabled),input:not(:disabled),[tabindex="0"]')).filter((el) => el.tabIndex >= 0 &&
1344
- el.getClientRects().length &&
1345
- getComputedStyle(el).visibility !== "hidden");
1346
- const first = controls[0], last = controls[controls.length - 1];
1347
- if (first &&
1348
- (event.shiftKey
1349
- ? this.document.activeElement === first
1350
- : this.document.activeElement === last)) {
1351
- event.preventDefault();
1352
- (event.shiftKey ? last : first).focus();
1353
- }
1354
- };
1355
- dialog.addEventListener("cancel", cancel);
1356
- dialog.addEventListener("click", click);
1357
- dialog.addEventListener("keydown", keydown);
1358
- dialog.showModal();
1359
- return {
1360
- component,
1361
- destroy: () => {
1362
- dialog.removeEventListener("cancel", cancel);
1363
- dialog.removeEventListener("click", click);
1364
- dialog.removeEventListener("keydown", keydown);
1365
- dialog.close();
1366
- this.app.detachView(component.hostView);
1367
- component.destroy();
1368
- dialog.remove();
1369
- trigger.focus();
1370
- },
1371
- };
1372
- }
1373
- }
1374
- WklyDateTimePickerDialogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WklyDateTimePickerDialogService, deps: [{ token: i0.ComponentFactoryResolver }, { token: i0.Injector }, { token: i0.ApplicationRef }, { token: DOCUMENT }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable });
1375
- WklyDateTimePickerDialogService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WklyDateTimePickerDialogService, providedIn: "root" });
1376
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WklyDateTimePickerDialogService, decorators: [{
1377
- type: Injectable,
1378
- args: [{ providedIn: "root" }]
1379
- }], ctorParameters: function () {
1380
- return [{ type: i0.ComponentFactoryResolver }, { type: i0.Injector }, { type: i0.ApplicationRef }, { type: Document, decorators: [{
1381
- type: Inject,
1382
- args: [DOCUMENT]
1383
- }] }, { type: Object, decorators: [{
1384
- type: Inject,
1385
- args: [PLATFORM_ID]
1386
- }] }];
1387
- } });
1388
- /** Shared trigger lifecycle; optional presentation packages extend this class. */
1389
- class WklyTriggerBase extends WklyPickerInputs {
1390
- constructor(element) {
1391
- super();
1392
- this.element = element;
1393
- this.ref = null;
1394
- this.subscriptions = [];
1395
- this.errors = [];
1396
- this.change = () => { };
1397
- this.touched = () => { };
1398
- this.validation = () => { };
1399
- }
1400
- open() {
1401
- if (this[WklyPickerInputsPropertyKeys.Disabled] || this.ref)
1402
- return;
1403
- this.ref = this.create();
1404
- const picker = this.ref.component.instance;
1405
- this.copy();
1406
- this.subscriptions = [
1407
- picker[WklyPickerOutputsPropertyKeys.ValueChange].subscribe((value) => {
1408
- this[WklyPickerInputsPropertyKeys.Value] = value;
1409
- this.change(value);
1410
- this[WklyPickerOutputsPropertyKeys.ValueChange].emit(value);
1411
- this.display();
1412
- }),
1413
- picker[WklyPickerOutputsPropertyKeys.ValidationChange].subscribe((errors) => {
1414
- this.errors = errors;
1415
- this[WklyPickerOutputsPropertyKeys.ValidationChange].emit(errors);
1416
- this.validation();
1417
- }),
1418
- picker[WklyPickerOutputsPropertyKeys.Closed].subscribe((reason) => this.close(reason)),
1419
- picker[WklyPickerOutputsPropertyKeys.ViewportChange].subscribe((value) => this[WklyPickerOutputsPropertyKeys.ViewportChange].emit(value)),
1420
- picker[WklyPickerOutputsPropertyKeys.ViewModeChange].subscribe((value) => this[WklyPickerOutputsPropertyKeys.ViewModeChange].emit(value)),
1421
- ];
1422
- this.ref.component.changeDetectorRef.detectChanges();
1423
- picker.focusDay();
1424
- this[WklyPickerOutputsPropertyKeys.Opened].emit();
1425
- }
1426
- key(event) {
1427
- if (event.key === "Enter" ||
1428
- event.key === " " ||
1429
- event.key === "ArrowDown") {
1430
- event.preventDefault();
1431
- this.open();
1432
- }
1433
- }
1434
- blur() {
1435
- this.touched();
1436
- }
1437
- close(reason = "programmatic") {
1438
- if (!this.ref)
1439
- return;
1440
- const ref = this.ref;
1441
- this.ref = null;
1442
- this.subscriptions.forEach((s) => s.unsubscribe());
1443
- this.subscriptions = [];
1444
- ref.destroy();
1445
- this.touched();
1446
- this[WklyPickerOutputsPropertyKeys.Closed].emit(reason);
1447
- }
1448
- ngOnChanges() {
1449
- [
1450
- WklyPickerInputsPropertyKeys.ShowSeconds,
1451
- WklyPickerInputsPropertyKeys.AllowRangeAcrossDisabled,
1452
- WklyPickerInputsPropertyKeys.Required,
1453
- WklyPickerInputsPropertyKeys.Disabled,
1454
- WklyPickerInputsPropertyKeys.CloseOnBackdrop,
1455
- ].forEach((key) => (this[key] = coerceBoolean(this[key])));
1456
- this.checkValue();
1457
- this.display();
1458
- if (this.ref) {
1459
- this.copy();
1460
- this.ref.component.instance.ngOnChanges({
1461
- [WklyPickerInputsPropertyKeys.Value]: true,
1462
- });
1463
- this.ref.component.changeDetectorRef.detectChanges();
1464
- }
1465
- }
1466
- ngOnDestroy() {
1467
- this.close();
1468
- }
1469
- copy() {
1470
- if (this.ref)
1471
- for (const name of INPUT_NAMES)
1472
- this.ref.component.instance[name] = this[name];
1473
- }
1474
- display() {
1475
- const host = this.element.nativeElement;
1476
- if (host.tagName === "INPUT") {
1477
- host.readOnly = true;
1478
- const value = this[WklyPickerInputsPropertyKeys.Value];
1479
- host.value =
1480
- value === null
1481
- ? ""
1482
- : typeof value === "string"
1483
- ? value
1484
- : value.join(" — ");
1485
- host.disabled = this[WklyPickerInputsPropertyKeys.Disabled];
1486
- host.setAttribute("aria-haspopup", "dialog");
1487
- }
1488
- }
1489
- checkValue() {
1490
- this.errors = validateSelection(this[WklyPickerInputsPropertyKeys.Value], this, this[WklyPickerInputsPropertyKeys.CalendarAdapter] ||
1491
- new WklyGregorianCalendarAdapter(this[WklyPickerInputsPropertyKeys.Locale] || "en-US"));
1492
- this[WklyPickerOutputsPropertyKeys.ValidationChange].emit(this.errors);
1493
- this.validation();
1494
- }
1495
- writeValue(value) {
1496
- this[WklyPickerInputsPropertyKeys.Value] = value;
1497
- this.checkValue();
1498
- this.display();
1499
- if (this.ref)
1500
- this.ref.component.instance.writeValue(value);
1501
- }
1502
- registerOnChange(fn) {
1503
- this.change = fn;
1504
- }
1505
- registerOnTouched(fn) {
1506
- this.touched = fn;
1507
- }
1508
- setDisabledState(value) {
1509
- this[WklyPickerInputsPropertyKeys.Disabled] = value;
1510
- this.display();
1511
- if (this.ref)
1512
- this.ref.component.instance.setDisabledState(value);
1513
- }
1514
- validate() {
1515
- return this.errors.length ? { wkly: this.errors } : null;
1516
- }
1517
- registerOnValidatorChange(fn) {
1518
- this.validation = fn;
1519
- }
1520
- scrollToEpochDay(day, options) {
1521
- var _a;
1522
- this.open();
1523
- (_a = this.ref) === null || _a === void 0 ? void 0 : _a.component.instance.scrollToEpochDay(day, options);
1524
- }
1525
- scrollToAbsoluteWeek(week, options) {
1526
- var _a;
1527
- this.open();
1528
- (_a = this.ref) === null || _a === void 0 ? void 0 : _a.component.instance.scrollToAbsoluteWeek(week, options);
1529
- }
1530
- scrollToCalendarDate(date, options) {
1531
- var _a;
1532
- this.open();
1533
- (_a = this.ref) === null || _a === void 0 ? void 0 : _a.component.instance.scrollToCalendarDate(date, options);
1534
- }
1535
- scrollToValue(value, options) {
1536
- var _a;
1537
- this.open();
1538
- (_a = this.ref) === null || _a === void 0 ? void 0 : _a.component.instance.scrollToValue(value, options);
1539
- }
1540
- }
1541
- WklyTriggerBase.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WklyTriggerBase, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
1542
- WklyTriggerBase.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.3.0", type: WklyTriggerBase, host: { listeners: { "click": "open()", "keydown": "key($event)", "blur": "blur()" } }, usesInheritance: true, usesOnChanges: true, ngImport: i0 });
1543
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WklyTriggerBase, decorators: [{
1544
- type: Directive
1545
- }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { open: [{
1546
- type: HostListener,
1547
- args: ["click"]
1548
- }], key: [{
1549
- type: HostListener,
1550
- args: ["keydown", ["$event"]]
1551
- }], blur: [{
1552
- type: HostListener,
1553
- args: ["blur"]
1554
- }] } });
1555
- class WklyDateTimePickerDialogDirective extends WklyTriggerBase {
1556
- constructor(element, service, triggerInjector) {
1557
- super(element);
1558
- this.service = service;
1559
- this.triggerInjector = triggerInjector;
1560
- }
1561
- create() {
1562
- return this.service.open(this.element.nativeElement, (reason) => this.close(reason), this[WklyPickerInputsPropertyKeys.CloseOnBackdrop], this.triggerInjector);
1563
- }
1564
- }
1565
- WklyDateTimePickerDialogDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WklyDateTimePickerDialogDirective, deps: [{ token: i0.ElementRef }, { token: WklyDateTimePickerDialogService }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Directive });
1566
- WklyDateTimePickerDialogDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.3.0", type: WklyDateTimePickerDialogDirective, selector: "[wklyDateTimePickerDialog]", providers: [
1567
- {
1568
- provide: NG_VALUE_ACCESSOR,
1569
- useExisting: forwardRef(() => WklyDateTimePickerDialogDirective),
1570
- multi: true,
1571
- },
1572
- {
1573
- provide: NG_VALIDATORS,
1574
- useExisting: forwardRef(() => WklyDateTimePickerDialogDirective),
1575
- multi: true,
1576
- },
1577
- ], exportAs: ["wklyDialog"], usesInheritance: true, ngImport: i0 });
1578
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WklyDateTimePickerDialogDirective, decorators: [{
1579
- type: Directive,
1580
- args: [{
1581
- selector: "[wklyDateTimePickerDialog]",
1582
- exportAs: "wklyDialog",
1583
- providers: [
1584
- {
1585
- provide: NG_VALUE_ACCESSOR,
1586
- useExisting: forwardRef(() => WklyDateTimePickerDialogDirective),
1587
- multi: true,
1588
- },
1589
- {
1590
- provide: NG_VALIDATORS,
1591
- useExisting: forwardRef(() => WklyDateTimePickerDialogDirective),
1592
- multi: true,
1593
- },
1594
- ],
1595
- }]
1596
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: WklyDateTimePickerDialogService }, { type: i0.Injector }]; } });
1597
-
1598
- class WklyDateTimePickerModule {
1599
- }
1600
- WklyDateTimePickerModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WklyDateTimePickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1601
- WklyDateTimePickerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: WklyDateTimePickerModule, declarations: [WklyDateTimePickerComponent,
1602
- WklyDateTimePickerDialogDirective,
1603
- WklyFieldComponent], imports: [CommonModule], exports: [WklyDateTimePickerComponent, WklyDateTimePickerDialogDirective] });
1604
- WklyDateTimePickerModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WklyDateTimePickerModule, imports: [CommonModule] });
1605
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: WklyDateTimePickerModule, decorators: [{
1606
- type: NgModule,
1607
- args: [{
1608
- imports: [CommonModule],
1609
- declarations: [
1610
- WklyDateTimePickerComponent,
1611
- WklyDateTimePickerDialogDirective,
1612
- WklyFieldComponent,
1613
- ],
1614
- entryComponents: [WklyDateTimePickerComponent],
1615
- exports: [WklyDateTimePickerComponent, WklyDateTimePickerDialogDirective],
1616
- }]
1617
- }] });
1618
-
1619
- /**
1620
- * Generated bundle index. Do not edit.
1621
- */
1622
-
1623
- export { WKLY_CLOCK, WKLY_CONFIG, WKLY_LOCALIZATION, WKLY_TRANSLATIONS, WklyDateTimePickerComponent, WklyDateTimePickerDialogDirective, WklyDateTimePickerDialogService, WklyDateTimePickerModule, WklyFieldComponent, WklyPickerInputs, WklyTriggerBase };
1624
- //# sourceMappingURL=wkly-datetime-picker.mjs.map