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