@skyux/datetime 5.7.2 → 6.0.0-beta.2

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 (160) hide show
  1. package/esm2020/index.mjs +28 -0
  2. package/esm2020/lib/modules/date-pipe/date-format-utility.mjs +46 -0
  3. package/esm2020/lib/modules/date-pipe/date-pipe.module.mjs +21 -0
  4. package/esm2020/lib/modules/date-pipe/date.pipe.mjs +65 -0
  5. package/esm2020/lib/modules/date-pipe/fuzzy-date.pipe.mjs +47 -0
  6. package/esm2020/lib/modules/date-range-picker/date-range-picker.component.mjs +448 -0
  7. package/esm2020/lib/modules/date-range-picker/date-range-picker.module.mjs +47 -0
  8. package/esm2020/lib/modules/date-range-picker/date-range.service.mjs +97 -0
  9. package/esm2020/lib/modules/date-range-picker/types/date-range-calculation.mjs +2 -0
  10. package/esm2020/lib/modules/date-range-picker/types/date-range-calculator-config.mjs +2 -0
  11. package/esm2020/lib/modules/date-range-picker/types/date-range-calculator-date-range-function.mjs +2 -0
  12. package/esm2020/lib/modules/date-range-picker/types/date-range-calculator-id.mjs +118 -0
  13. package/esm2020/lib/modules/date-range-picker/types/date-range-calculator-type.mjs +23 -0
  14. package/esm2020/lib/modules/date-range-picker/types/date-range-calculator-validate-function.mjs +2 -0
  15. package/esm2020/lib/modules/date-range-picker/types/date-range-calculator.mjs +56 -0
  16. package/esm2020/lib/modules/date-range-picker/types/date-range-default-calculator-config.mjs +2 -0
  17. package/esm2020/lib/modules/date-range-picker/types/date-range-default-calculator-configs.mjs +147 -0
  18. package/esm2020/lib/modules/date-range-picker/types/date-range-relative-value.mjs +249 -0
  19. package/esm2020/lib/modules/date-range-picker/types/date-range.mjs +2 -0
  20. package/esm2020/lib/modules/datepicker/date-formatter.mjs +38 -0
  21. package/esm2020/lib/modules/datepicker/datepicker-adapter.service.mjs +33 -0
  22. package/esm2020/lib/modules/datepicker/datepicker-calendar-change.mjs +2 -0
  23. package/esm2020/lib/modules/datepicker/datepicker-calendar-inner.component.mjs +310 -0
  24. package/esm2020/lib/modules/datepicker/datepicker-calendar.component.mjs +104 -0
  25. package/esm2020/lib/modules/datepicker/datepicker-config.service.mjs +21 -0
  26. package/esm2020/lib/modules/datepicker/datepicker-custom-date.mjs +2 -0
  27. package/esm2020/lib/modules/datepicker/datepicker-date.mjs +2 -0
  28. package/esm2020/lib/modules/datepicker/datepicker-input-fuzzy.directive.mjs +466 -0
  29. package/esm2020/lib/modules/datepicker/datepicker-input.directive.mjs +445 -0
  30. package/esm2020/lib/modules/datepicker/datepicker.component.mjs +328 -0
  31. package/esm2020/lib/modules/datepicker/datepicker.module.mjs +95 -0
  32. package/esm2020/lib/modules/datepicker/datepicker.service.mjs +21 -0
  33. package/esm2020/lib/modules/datepicker/daypicker-button.component.mjs +22 -0
  34. package/esm2020/lib/modules/datepicker/daypicker-cell.component.mjs +126 -0
  35. package/esm2020/lib/modules/datepicker/daypicker.component.mjs +211 -0
  36. package/esm2020/lib/modules/datepicker/fuzzy-date.mjs +2 -0
  37. package/esm2020/lib/modules/datepicker/fuzzy-date.service.mjs +403 -0
  38. package/esm2020/lib/modules/datepicker/monthpicker.component.mjs +80 -0
  39. package/esm2020/lib/modules/datepicker/yearpicker.component.mjs +86 -0
  40. package/esm2020/lib/modules/shared/sky-datetime-resources.module.mjs +131 -0
  41. package/esm2020/lib/modules/timepicker/timepicker.component.mjs +361 -0
  42. package/esm2020/lib/modules/timepicker/timepicker.directive.mjs +228 -0
  43. package/esm2020/lib/modules/timepicker/timepicker.interface.mjs +2 -0
  44. package/esm2020/lib/modules/timepicker/timepicker.module.mjs +46 -0
  45. package/esm2020/skyux-datetime.mjs +5 -0
  46. package/esm2020/testing/datepicker-fixture.mjs +54 -0
  47. package/esm2020/testing/public-api.mjs +3 -0
  48. package/esm2020/testing/skyux-datetime-testing.mjs +5 -0
  49. package/esm2020/testing/timepicker-fixture.mjs +50 -0
  50. package/fesm2015/{skyux-datetime-testing.js → skyux-datetime-testing.mjs} +1 -1
  51. package/fesm2015/skyux-datetime-testing.mjs.map +1 -0
  52. package/fesm2015/skyux-datetime.mjs +4726 -0
  53. package/fesm2015/skyux-datetime.mjs.map +1 -0
  54. package/{esm2015/testing/datepicker-fixture.js → fesm2020/skyux-datetime-testing.mjs} +57 -2
  55. package/fesm2020/skyux-datetime-testing.mjs.map +1 -0
  56. package/{fesm2015/skyux-datetime.js → fesm2020/skyux-datetime.mjs} +110 -158
  57. package/fesm2020/skyux-datetime.mjs.map +1 -0
  58. package/package.json +42 -18
  59. package/testing/package.json +5 -5
  60. package/bundles/skyux-datetime-testing.umd.js +0 -143
  61. package/bundles/skyux-datetime.umd.js +0 -5488
  62. package/esm2015/index.js +0 -28
  63. package/esm2015/index.js.map +0 -1
  64. package/esm2015/lib/modules/date-pipe/date-format-utility.js +0 -46
  65. package/esm2015/lib/modules/date-pipe/date-format-utility.js.map +0 -1
  66. package/esm2015/lib/modules/date-pipe/date-pipe.module.js +0 -21
  67. package/esm2015/lib/modules/date-pipe/date-pipe.module.js.map +0 -1
  68. package/esm2015/lib/modules/date-pipe/date.pipe.js +0 -65
  69. package/esm2015/lib/modules/date-pipe/date.pipe.js.map +0 -1
  70. package/esm2015/lib/modules/date-pipe/fuzzy-date.pipe.js +0 -47
  71. package/esm2015/lib/modules/date-pipe/fuzzy-date.pipe.js.map +0 -1
  72. package/esm2015/lib/modules/date-range-picker/date-range-picker.component.js +0 -453
  73. package/esm2015/lib/modules/date-range-picker/date-range-picker.component.js.map +0 -1
  74. package/esm2015/lib/modules/date-range-picker/date-range-picker.module.js +0 -47
  75. package/esm2015/lib/modules/date-range-picker/date-range-picker.module.js.map +0 -1
  76. package/esm2015/lib/modules/date-range-picker/date-range.service.js +0 -97
  77. package/esm2015/lib/modules/date-range-picker/date-range.service.js.map +0 -1
  78. package/esm2015/lib/modules/date-range-picker/types/date-range-calculation.js +0 -2
  79. package/esm2015/lib/modules/date-range-picker/types/date-range-calculation.js.map +0 -1
  80. package/esm2015/lib/modules/date-range-picker/types/date-range-calculator-config.js +0 -2
  81. package/esm2015/lib/modules/date-range-picker/types/date-range-calculator-config.js.map +0 -1
  82. package/esm2015/lib/modules/date-range-picker/types/date-range-calculator-date-range-function.js +0 -2
  83. package/esm2015/lib/modules/date-range-picker/types/date-range-calculator-date-range-function.js.map +0 -1
  84. package/esm2015/lib/modules/date-range-picker/types/date-range-calculator-id.js +0 -118
  85. package/esm2015/lib/modules/date-range-picker/types/date-range-calculator-id.js.map +0 -1
  86. package/esm2015/lib/modules/date-range-picker/types/date-range-calculator-type.js +0 -23
  87. package/esm2015/lib/modules/date-range-picker/types/date-range-calculator-type.js.map +0 -1
  88. package/esm2015/lib/modules/date-range-picker/types/date-range-calculator-validate-function.js +0 -2
  89. package/esm2015/lib/modules/date-range-picker/types/date-range-calculator-validate-function.js.map +0 -1
  90. package/esm2015/lib/modules/date-range-picker/types/date-range-calculator.js +0 -56
  91. package/esm2015/lib/modules/date-range-picker/types/date-range-calculator.js.map +0 -1
  92. package/esm2015/lib/modules/date-range-picker/types/date-range-default-calculator-config.js +0 -2
  93. package/esm2015/lib/modules/date-range-picker/types/date-range-default-calculator-config.js.map +0 -1
  94. package/esm2015/lib/modules/date-range-picker/types/date-range-default-calculator-configs.js +0 -147
  95. package/esm2015/lib/modules/date-range-picker/types/date-range-default-calculator-configs.js.map +0 -1
  96. package/esm2015/lib/modules/date-range-picker/types/date-range-relative-value.js +0 -249
  97. package/esm2015/lib/modules/date-range-picker/types/date-range-relative-value.js.map +0 -1
  98. package/esm2015/lib/modules/date-range-picker/types/date-range.js +0 -2
  99. package/esm2015/lib/modules/date-range-picker/types/date-range.js.map +0 -1
  100. package/esm2015/lib/modules/datepicker/date-formatter.js +0 -38
  101. package/esm2015/lib/modules/datepicker/date-formatter.js.map +0 -1
  102. package/esm2015/lib/modules/datepicker/datepicker-adapter.service.js +0 -33
  103. package/esm2015/lib/modules/datepicker/datepicker-adapter.service.js.map +0 -1
  104. package/esm2015/lib/modules/datepicker/datepicker-calendar-change.js +0 -2
  105. package/esm2015/lib/modules/datepicker/datepicker-calendar-change.js.map +0 -1
  106. package/esm2015/lib/modules/datepicker/datepicker-calendar-inner.component.js +0 -315
  107. package/esm2015/lib/modules/datepicker/datepicker-calendar-inner.component.js.map +0 -1
  108. package/esm2015/lib/modules/datepicker/datepicker-calendar.component.js +0 -109
  109. package/esm2015/lib/modules/datepicker/datepicker-calendar.component.js.map +0 -1
  110. package/esm2015/lib/modules/datepicker/datepicker-config.service.js +0 -21
  111. package/esm2015/lib/modules/datepicker/datepicker-config.service.js.map +0 -1
  112. package/esm2015/lib/modules/datepicker/datepicker-custom-date.js +0 -2
  113. package/esm2015/lib/modules/datepicker/datepicker-custom-date.js.map +0 -1
  114. package/esm2015/lib/modules/datepicker/datepicker-date.js +0 -2
  115. package/esm2015/lib/modules/datepicker/datepicker-date.js.map +0 -1
  116. package/esm2015/lib/modules/datepicker/datepicker-input-fuzzy.directive.js +0 -467
  117. package/esm2015/lib/modules/datepicker/datepicker-input-fuzzy.directive.js.map +0 -1
  118. package/esm2015/lib/modules/datepicker/datepicker-input.directive.js +0 -446
  119. package/esm2015/lib/modules/datepicker/datepicker-input.directive.js.map +0 -1
  120. package/esm2015/lib/modules/datepicker/datepicker.component.js +0 -333
  121. package/esm2015/lib/modules/datepicker/datepicker.component.js.map +0 -1
  122. package/esm2015/lib/modules/datepicker/datepicker.module.js +0 -95
  123. package/esm2015/lib/modules/datepicker/datepicker.module.js.map +0 -1
  124. package/esm2015/lib/modules/datepicker/datepicker.service.js +0 -21
  125. package/esm2015/lib/modules/datepicker/datepicker.service.js.map +0 -1
  126. package/esm2015/lib/modules/datepicker/daypicker-button.component.js +0 -26
  127. package/esm2015/lib/modules/datepicker/daypicker-button.component.js.map +0 -1
  128. package/esm2015/lib/modules/datepicker/daypicker-cell.component.js +0 -130
  129. package/esm2015/lib/modules/datepicker/daypicker-cell.component.js.map +0 -1
  130. package/esm2015/lib/modules/datepicker/daypicker.component.js +0 -215
  131. package/esm2015/lib/modules/datepicker/daypicker.component.js.map +0 -1
  132. package/esm2015/lib/modules/datepicker/fuzzy-date.js +0 -2
  133. package/esm2015/lib/modules/datepicker/fuzzy-date.js.map +0 -1
  134. package/esm2015/lib/modules/datepicker/fuzzy-date.service.js +0 -403
  135. package/esm2015/lib/modules/datepicker/fuzzy-date.service.js.map +0 -1
  136. package/esm2015/lib/modules/datepicker/monthpicker.component.js +0 -84
  137. package/esm2015/lib/modules/datepicker/monthpicker.component.js.map +0 -1
  138. package/esm2015/lib/modules/datepicker/yearpicker.component.js +0 -90
  139. package/esm2015/lib/modules/datepicker/yearpicker.component.js.map +0 -1
  140. package/esm2015/lib/modules/shared/sky-datetime-resources.module.js +0 -131
  141. package/esm2015/lib/modules/shared/sky-datetime-resources.module.js.map +0 -1
  142. package/esm2015/lib/modules/timepicker/timepicker.component.js +0 -367
  143. package/esm2015/lib/modules/timepicker/timepicker.component.js.map +0 -1
  144. package/esm2015/lib/modules/timepicker/timepicker.directive.js +0 -228
  145. package/esm2015/lib/modules/timepicker/timepicker.directive.js.map +0 -1
  146. package/esm2015/lib/modules/timepicker/timepicker.interface.js +0 -2
  147. package/esm2015/lib/modules/timepicker/timepicker.interface.js.map +0 -1
  148. package/esm2015/lib/modules/timepicker/timepicker.module.js +0 -46
  149. package/esm2015/lib/modules/timepicker/timepicker.module.js.map +0 -1
  150. package/esm2015/skyux-datetime.js +0 -5
  151. package/esm2015/skyux-datetime.js.map +0 -1
  152. package/esm2015/testing/datepicker-fixture.js.map +0 -1
  153. package/esm2015/testing/public-api.js +0 -3
  154. package/esm2015/testing/public-api.js.map +0 -1
  155. package/esm2015/testing/skyux-datetime-testing.js +0 -5
  156. package/esm2015/testing/skyux-datetime-testing.js.map +0 -1
  157. package/esm2015/testing/timepicker-fixture.js +0 -50
  158. package/esm2015/testing/timepicker-fixture.js.map +0 -1
  159. package/fesm2015/skyux-datetime-testing.js.map +0 -1
  160. package/fesm2015/skyux-datetime.js.map +0 -1
@@ -0,0 +1,4726 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Pipe, NgModule, Injectable, EventEmitter, Component, ViewEncapsulation, Input, Output, ChangeDetectionStrategy, ViewChild, ElementRef, TemplateRef, Optional, forwardRef, Directive, HostListener } from '@angular/core';
3
+ import { Subject, fromEvent, BehaviorSubject, forkJoin, combineLatest } from 'rxjs';
4
+ import { takeUntil, debounceTime, distinctUntilChanged, first, map } from 'rxjs/operators';
5
+ import * as i3 from '@skyux/i18n';
6
+ import { SkyIntlDateFormatter, getLibStringForLocale, SkyI18nModule, SKY_LIB_RESOURCES_PROVIDERS } from '@skyux/i18n';
7
+ import moment from 'moment';
8
+ import * as i5 from '@angular/common';
9
+ import { CommonModule } from '@angular/common';
10
+ import * as i2$2 from '@angular/forms';
11
+ import { NG_VALUE_ACCESSOR, NG_VALIDATORS, FormsModule, FormControl, ReactiveFormsModule } from '@angular/forms';
12
+ import * as i2$1 from '@skyux/forms';
13
+ import { SkyInputBoxModule } from '@skyux/forms';
14
+ import * as i1 from '@skyux/core';
15
+ import { SkyAffixAutoFitContext, SkyAffixModule, SkyOverlayModule } from '@skyux/core';
16
+ import * as i2 from '@skyux/indicators';
17
+ import { SkyIconModule, SkyWaitModule } from '@skyux/indicators';
18
+ import * as i3$1 from '@skyux/popovers';
19
+ import { SkyPopoverMessageType, SkyPopoverModule } from '@skyux/popovers';
20
+ import * as i3$2 from '@skyux/theme';
21
+ import { SkyThemeModule } from '@skyux/theme';
22
+
23
+ // This class is mostly ported from the Angular 4.x DatePipe in order to maintain the old
24
+ class SkyDateFormatUtility {
25
+ static format(locale, value, pattern) {
26
+ let date;
27
+ if (isBlank(value) || value !== value) {
28
+ return undefined;
29
+ }
30
+ // Moment will interpret any non-date object as today's date. That would
31
+ // introduce a breaking change, so we check for it here. This could probably be removed
32
+ // in a future major version.
33
+ if (value instanceof Object && !(value instanceof Date)) {
34
+ handleInvalidDate(value);
35
+ }
36
+ // Use moment to avoid inconsistencies between browsers interpreting the value differently.
37
+ const momentDate = moment(value);
38
+ if (momentDate.isValid()) {
39
+ date = momentDate.toDate();
40
+ }
41
+ else {
42
+ handleInvalidDate(value);
43
+ }
44
+ return SkyIntlDateFormatter.format(date, locale, SkyDateFormatUtility._ALIASES[pattern] || pattern);
45
+ }
46
+ }
47
+ SkyDateFormatUtility._ALIASES = {
48
+ medium: 'yMMMdjms',
49
+ short: 'yMdjm',
50
+ fullDate: 'yMMMMEEEEd',
51
+ longDate: 'yMMMMd',
52
+ mediumDate: 'yMMMd',
53
+ shortDate: 'yMd',
54
+ mediumTime: 'jms',
55
+ shortTime: 'jm',
56
+ };
57
+ function isBlank(obj) {
58
+ return !obj;
59
+ }
60
+ function handleInvalidDate(value) {
61
+ throw new Error('Invalid value: ' + value);
62
+ }
63
+
64
+ /**
65
+ * Formats date values according to locale rules.
66
+ * @example
67
+ * ```markup
68
+ * {{ myDate | skyDate }}
69
+ * {{ myDate | skyDate:'medium' }}
70
+ * {{ myDate | skyDate:'medium':'en-CA' }}
71
+ * ```
72
+ */
73
+ class SkyDatePipe {
74
+ constructor(localeProvider) {
75
+ this.localeProvider = localeProvider;
76
+ this.defaultFormat = 'short';
77
+ this.defaultLocale = 'en-US';
78
+ this.ngUnsubscribe = new Subject();
79
+ this.localeProvider
80
+ .getLocaleInfo()
81
+ .pipe(takeUntil(this.ngUnsubscribe))
82
+ .subscribe((localeInfo) => {
83
+ this.defaultLocale = localeInfo.locale;
84
+ this.updateFormattedValue();
85
+ });
86
+ }
87
+ ngOnDestroy() {
88
+ this.ngUnsubscribe.next();
89
+ this.ngUnsubscribe.complete();
90
+ }
91
+ /**
92
+ * Transforms a date value using locale and format rules.
93
+ * @param value Specifies the date value to transform.
94
+ * @param format Specifies the format to apply to the transform. The format string is
95
+ * constructed by a series of symbols that represent date-time values. The symbols are
96
+ * identical to [Angular's `DatePipe`](https://angular.io/api/common/DatePipe#pre-defined-format-options) format options.
97
+ * @param locale Specifies the locale code to use in the transform.
98
+ */
99
+ transform(value, format, locale) {
100
+ this.value = value;
101
+ this.format = format;
102
+ this.locale = locale;
103
+ this.updateFormattedValue();
104
+ return this.formattedValue;
105
+ }
106
+ updateFormattedValue() {
107
+ const locale = this.locale || this.defaultLocale;
108
+ const format = this.format || this.defaultFormat;
109
+ this.formattedValue = SkyDateFormatUtility.format(locale, this.value, format);
110
+ }
111
+ }
112
+ SkyDatePipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatePipe, deps: [{ token: i3.SkyAppLocaleProvider }], target: i0.ɵɵFactoryTarget.Pipe });
113
+ SkyDatePipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatePipe, name: "skyDate", pure: false });
114
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatePipe, decorators: [{
115
+ type: Pipe,
116
+ args: [{
117
+ name: 'skyDate',
118
+ pure: false,
119
+ }]
120
+ }], ctorParameters: function () { return [{ type: i3.SkyAppLocaleProvider }]; } });
121
+
122
+ /**
123
+ * NOTICE: DO NOT MODIFY THIS FILE!
124
+ * The contents of this file were automatically generated by
125
+ * the 'ng generate @skyux/i18n:lib-resources-module lib/modules/shared/sky-datetime' schematic.
126
+ * To update this file, simply rerun the command.
127
+ */
128
+ const RESOURCES = {
129
+ 'EN-AU': {
130
+ skyux_date_range_picker_format_label_last_fiscal_year: {
131
+ message: 'Last financial year',
132
+ },
133
+ skyux_date_range_picker_format_label_this_fiscal_year: {
134
+ message: 'This financial year',
135
+ },
136
+ skyux_date_range_picker_format_label_next_fiscal_year: {
137
+ message: 'Next financial year',
138
+ },
139
+ },
140
+ 'EN-GB': {
141
+ skyux_date_range_picker_format_label_last_fiscal_year: {
142
+ message: 'Last financial year',
143
+ },
144
+ skyux_date_range_picker_format_label_this_fiscal_year: {
145
+ message: 'This financial year',
146
+ },
147
+ skyux_date_range_picker_format_label_next_fiscal_year: {
148
+ message: 'Next financial year',
149
+ },
150
+ },
151
+ 'EN-NZ': {
152
+ skyux_date_range_picker_format_label_last_fiscal_year: {
153
+ message: 'Last financial year',
154
+ },
155
+ skyux_date_range_picker_format_label_this_fiscal_year: {
156
+ message: 'This financial year',
157
+ },
158
+ skyux_date_range_picker_format_label_next_fiscal_year: {
159
+ message: 'Next financial year',
160
+ },
161
+ },
162
+ 'EN-US': {
163
+ skyux_date_field_default_label: { message: 'Date' },
164
+ skyux_datepicker_trigger_button_label: { message: 'Select date' },
165
+ skyux_timepicker_button_label: { message: 'Choose time' },
166
+ skyux_timepicker_close: { message: 'Done' },
167
+ skyux_timepicker_input_default_label: { message: 'Time' },
168
+ skyux_date_range_picker_default_label: { message: 'Select a date range' },
169
+ skyux_date_range_picker_format_label_specific_range: {
170
+ message: 'Specific range',
171
+ },
172
+ skyux_date_range_picker_format_label_before: { message: 'Before' },
173
+ skyux_date_range_picker_format_label_after: { message: 'After' },
174
+ skyux_date_range_picker_format_label_any_time: { message: 'At any time' },
175
+ skyux_date_range_picker_format_label_yesterday: { message: 'Yesterday' },
176
+ skyux_date_range_picker_format_label_today: { message: 'Today' },
177
+ skyux_date_range_picker_format_label_tomorrow: { message: 'Tomorrow' },
178
+ skyux_date_range_picker_format_label_last_week: { message: 'Last week' },
179
+ skyux_date_range_picker_format_label_this_week: { message: 'This week' },
180
+ skyux_date_range_picker_format_label_next_week: { message: 'Next week' },
181
+ skyux_date_range_picker_format_label_last_month: { message: 'Last month' },
182
+ skyux_date_range_picker_format_label_this_month: { message: 'This month' },
183
+ skyux_date_range_picker_format_label_next_month: { message: 'Next month' },
184
+ skyux_date_range_picker_format_label_last_quarter: {
185
+ message: 'Last quarter',
186
+ },
187
+ skyux_date_range_picker_format_label_this_quarter: {
188
+ message: 'This quarter',
189
+ },
190
+ skyux_date_range_picker_format_label_next_quarter: {
191
+ message: 'Next quarter',
192
+ },
193
+ skyux_date_range_picker_format_label_last_calendar_year: {
194
+ message: 'Last calendar year',
195
+ },
196
+ skyux_date_range_picker_format_label_this_calendar_year: {
197
+ message: 'This calendar year',
198
+ },
199
+ skyux_date_range_picker_format_label_next_calendar_year: {
200
+ message: 'Next calendar year',
201
+ },
202
+ skyux_date_range_picker_format_label_last_fiscal_year: {
203
+ message: 'Last fiscal year',
204
+ },
205
+ skyux_date_range_picker_format_label_this_fiscal_year: {
206
+ message: 'This fiscal year',
207
+ },
208
+ skyux_date_range_picker_format_label_next_fiscal_year: {
209
+ message: 'Next fiscal year',
210
+ },
211
+ skyux_date_range_picker_start_date_label: { message: 'From date' },
212
+ skyux_date_range_picker_end_date_label: { message: 'To date' },
213
+ skyux_date_range_picker_before_date_label: { message: 'Before date' },
214
+ skyux_date_range_picker_after_date_label: { message: 'After date' },
215
+ },
216
+ };
217
+ class SkyDatetimeResourcesProvider {
218
+ getString(localeInfo, name) {
219
+ return getLibStringForLocale(RESOURCES, localeInfo.locale, name);
220
+ }
221
+ }
222
+ /**
223
+ * Import into any component library module that needs to use resource strings.
224
+ */
225
+ class SkyDatetimeResourcesModule {
226
+ }
227
+ SkyDatetimeResourcesModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatetimeResourcesModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
228
+ SkyDatetimeResourcesModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatetimeResourcesModule, exports: [SkyI18nModule] });
229
+ SkyDatetimeResourcesModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatetimeResourcesModule, providers: [
230
+ {
231
+ provide: SKY_LIB_RESOURCES_PROVIDERS,
232
+ useClass: SkyDatetimeResourcesProvider,
233
+ multi: true,
234
+ },
235
+ ], imports: [SkyI18nModule] });
236
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatetimeResourcesModule, decorators: [{
237
+ type: NgModule,
238
+ args: [{
239
+ exports: [SkyI18nModule],
240
+ providers: [
241
+ {
242
+ provide: SKY_LIB_RESOURCES_PROVIDERS,
243
+ useClass: SkyDatetimeResourcesProvider,
244
+ multi: true,
245
+ },
246
+ ],
247
+ }]
248
+ }] });
249
+
250
+ /**
251
+ * @internal
252
+ */
253
+ class SkyFuzzyDateService {
254
+ constructor(localeProvider) {
255
+ this.localeProvider = localeProvider;
256
+ this.ngUnsubscribe = new Subject();
257
+ this.localeProvider
258
+ .getLocaleInfo()
259
+ .pipe(takeUntil(this.ngUnsubscribe))
260
+ .subscribe((localeInfo) => {
261
+ this.currentLocale = localeInfo.locale;
262
+ });
263
+ }
264
+ /* istanbul ignore next */
265
+ ngOnDestroy() {
266
+ this.ngUnsubscribe.next();
267
+ this.ngUnsubscribe.complete();
268
+ }
269
+ /**
270
+ * Returns the browser's current locale string.
271
+ */
272
+ getCurrentLocale() {
273
+ return this.currentLocale;
274
+ }
275
+ /**
276
+ * Returns the short format of the provided locale.
277
+ * If not provided, the locale will be taken from the browser's default locale.
278
+ */
279
+ getLocaleShortFormat(locale) {
280
+ return moment.localeData(locale || this.currentLocale).longDateFormat('L');
281
+ }
282
+ /**
283
+ * Formats a fuzzy date by using the provided format and locale strings.
284
+ * If not provided, the locale will be taken from the browser's default locale.
285
+ */
286
+ format(fuzzyDate, format, locale) {
287
+ if (!this.isFuzzyDateValid(fuzzyDate)) {
288
+ return '';
289
+ }
290
+ if (!format) {
291
+ return '';
292
+ }
293
+ const separator = this.getDateSeparator(format);
294
+ const dateParts = [];
295
+ const formatTokens = format.split(separator);
296
+ locale = locale || this.currentLocale;
297
+ const fuzzyDateMoment = this.getMomentFromFuzzyDate(fuzzyDate).locale(locale);
298
+ for (let index = 0; index < formatTokens.length; index++) {
299
+ const token = formatTokens[index];
300
+ /* istanbul ignore else */
301
+ if (token) {
302
+ // tslint:disable-next-line: switch-default
303
+ switch (token.substr(0, 1).toLowerCase()) {
304
+ case 'y':
305
+ if (fuzzyDate.year) {
306
+ dateParts.push(fuzzyDateMoment.format(token));
307
+ }
308
+ break;
309
+ case 'm':
310
+ if (fuzzyDate.month) {
311
+ dateParts.push(fuzzyDateMoment.format(token));
312
+ }
313
+ break;
314
+ case 'd':
315
+ if (fuzzyDate.day) {
316
+ dateParts.push(fuzzyDateMoment.format(token));
317
+ }
318
+ break;
319
+ }
320
+ }
321
+ }
322
+ return dateParts.join(separator);
323
+ }
324
+ /**
325
+ * If not provided, years will default to current year; months will default to January;
326
+ * days will default to 1st of the month.
327
+ */
328
+ getMomentFromFuzzyDate(fuzzyDate) {
329
+ if (!fuzzyDate) {
330
+ return;
331
+ }
332
+ const year = fuzzyDate.year || this.getDefaultYear(fuzzyDate);
333
+ const month = fuzzyDate.month > 0 ? fuzzyDate.month - 1 : 0;
334
+ const day = fuzzyDate.day || 1;
335
+ return moment([year, month, day]);
336
+ }
337
+ /**
338
+ * Gets a string instance of a fuzzy date.
339
+ * @deprecated Deprecated in favor of the `format` function.
340
+ */
341
+ getStringFromFuzzyDate(fuzzyDate, dateFormat) {
342
+ if (!fuzzyDate || !dateFormat) {
343
+ return;
344
+ }
345
+ const separator = this.getDateSeparator(dateFormat);
346
+ const dateFormatIndexes = this.getDateFormatIndexes(dateFormat);
347
+ let dateString = '';
348
+ // Get the components of the date in the order expected of the local format.
349
+ const dateComponents = [
350
+ { value: fuzzyDate.year || 0, index: dateFormatIndexes.yearIndex },
351
+ { value: fuzzyDate.month || 0, index: dateFormatIndexes.monthIndex },
352
+ { value: fuzzyDate.day || 0, index: dateFormatIndexes.dayIndex },
353
+ ];
354
+ dateComponents.sort((a, b) => a.index - b.index);
355
+ dateComponents.forEach((component) => {
356
+ if (component.value > 0 && component.index > -1) {
357
+ if (dateString) {
358
+ dateString += separator;
359
+ }
360
+ dateString += component.value.toString();
361
+ }
362
+ });
363
+ return dateString.trim();
364
+ }
365
+ getFuzzyDateFromSelectedDate(selectedDate, dateFormat) {
366
+ if (!selectedDate || !dateFormat) {
367
+ return;
368
+ }
369
+ const fuzzyDate = {};
370
+ const dateFormatIndexes = this.getDateFormatIndexes(dateFormat);
371
+ if (dateFormatIndexes.yearIndex > -1) {
372
+ fuzzyDate.year = selectedDate.getFullYear();
373
+ }
374
+ if (dateFormatIndexes.dayIndex > -1) {
375
+ fuzzyDate.day = selectedDate.getDate();
376
+ }
377
+ if (dateFormatIndexes.monthIndex > -1) {
378
+ fuzzyDate.month = selectedDate.getMonth() + 1; // getMonth() is 0-indexed.
379
+ }
380
+ return fuzzyDate;
381
+ }
382
+ getFuzzyDateFromString(date, dateFormat) {
383
+ if (!date || !dateFormat) {
384
+ return;
385
+ }
386
+ let day;
387
+ let month;
388
+ let year;
389
+ const dateComponents = this.getDateComponents(date);
390
+ const indexes = this.getDateValueIndexes(date, dateFormat);
391
+ // Look at the date string's component count:
392
+ // 3 indicates a full date
393
+ // 2 indicates a month-year or month-day date
394
+ // 1 indicates a year
395
+ // Other indicates a problem
396
+ switch (dateComponents.length) {
397
+ case 3:
398
+ year = dateComponents[indexes.yearIndex];
399
+ month = dateComponents[indexes.monthIndex];
400
+ day = dateComponents[indexes.dayIndex];
401
+ break;
402
+ case 2:
403
+ // First, check for a 4-digit year. If year exists, then we assume the other component
404
+ // is the month. Otherwise, we can assume the input is mm/dd or mm/yy (2-digit year).
405
+ year = this.get4DigitYearFromDateString(date);
406
+ if (year) {
407
+ month =
408
+ dateComponents[0] === year.toString()
409
+ ? dateComponents[1]
410
+ : dateComponents[0];
411
+ }
412
+ else {
413
+ if (indexes.dayIndex > -1) {
414
+ // mm/dd
415
+ month =
416
+ indexes.monthIndex < indexes.dayIndex
417
+ ? dateComponents[0]
418
+ : dateComponents[1];
419
+ day =
420
+ month === dateComponents[1]
421
+ ? dateComponents[0]
422
+ : dateComponents[1];
423
+ }
424
+ else {
425
+ // mm/yy
426
+ month =
427
+ indexes.monthIndex < indexes.yearIndex
428
+ ? dateComponents[0]
429
+ : dateComponents[1];
430
+ year =
431
+ month === dateComponents[1]
432
+ ? dateComponents[0]
433
+ : dateComponents[1];
434
+ }
435
+ }
436
+ break;
437
+ case 1:
438
+ year = date;
439
+ break;
440
+ default:
441
+ return;
442
+ }
443
+ if (month) {
444
+ // Check if month is valid.
445
+ month = this.getMonthNumber(month);
446
+ if (month === undefined) {
447
+ return;
448
+ }
449
+ // Check if day is valid.
450
+ if (day) {
451
+ day = parseInt(day, 10);
452
+ const fuzzyMoment = this.getMomentFromFuzzyDate({
453
+ month: month,
454
+ day: day,
455
+ year: year,
456
+ });
457
+ if (isNaN(day) || !fuzzyMoment.isValid()) {
458
+ return;
459
+ }
460
+ }
461
+ }
462
+ if (year) {
463
+ year =
464
+ year.toString().length === 2
465
+ ? moment.parseTwoDigitYear(year)
466
+ : parseInt(year.toString(), 10);
467
+ if (isNaN(year) || year.toString().length !== 4) {
468
+ return;
469
+ }
470
+ }
471
+ return {
472
+ month: month,
473
+ day: day,
474
+ year: year,
475
+ };
476
+ }
477
+ getFuzzyDateRange(startFuzzyDate, endFuzzyDate) {
478
+ let start;
479
+ let end;
480
+ let days;
481
+ let months;
482
+ let years;
483
+ let valid = false;
484
+ if (startFuzzyDate &&
485
+ startFuzzyDate.year &&
486
+ endFuzzyDate &&
487
+ endFuzzyDate.year) {
488
+ start = this.getMomentFromFuzzyDate(startFuzzyDate);
489
+ end = this.getMomentFromFuzzyDate(endFuzzyDate);
490
+ years = end.diff(start, 'years');
491
+ months = end.diff(start, 'months');
492
+ days = end.diff(start, 'days');
493
+ valid = end.diff(start) >= 0;
494
+ }
495
+ return {
496
+ years: years,
497
+ months: months,
498
+ days: days,
499
+ valid: valid,
500
+ };
501
+ }
502
+ getCurrentFuzzyDate() {
503
+ const currentDate = moment();
504
+ return {
505
+ day: currentDate.date(),
506
+ month: currentDate.month() + 1,
507
+ year: currentDate.year(),
508
+ };
509
+ }
510
+ getMostRecentLeapYear() {
511
+ let leapYear = new Date().getFullYear();
512
+ while (!this.isLeapYear(leapYear)) {
513
+ leapYear -= 1;
514
+ }
515
+ return leapYear;
516
+ }
517
+ /**
518
+ * Returns the first separator found in the provided date format string.
519
+ * Accepted separators: ['/', '.', '-', ' '].
520
+ * @param dateFormat
521
+ */
522
+ getDateSeparator(dateFormat) {
523
+ let returnValue;
524
+ const separators = ['/', '.', '-', ' '];
525
+ separators.forEach((separator) => {
526
+ if (!returnValue && dateFormat.indexOf(separator) > 0) {
527
+ returnValue = separator;
528
+ }
529
+ });
530
+ return returnValue;
531
+ }
532
+ get4DigitYearFromDateString(date) {
533
+ let year;
534
+ const separator = this.getDateSeparator(date);
535
+ // Find the number value in the string that is 4 digits long.
536
+ date.split(separator).forEach((dateComponent) => {
537
+ if (!year && parseInt(dateComponent, 10).toString().length === 4) {
538
+ year = dateComponent;
539
+ }
540
+ });
541
+ if (year && !isNaN(Number(year))) {
542
+ return parseInt(year, 10);
543
+ }
544
+ }
545
+ isLeapYear(year) {
546
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
547
+ }
548
+ getMonthNumber(month) {
549
+ let returnValue;
550
+ const monthAsNumber = parseInt(month, 10);
551
+ // If the month component is a string ("Janaury"), we check to see if it is a valid month
552
+ if (isNaN(monthAsNumber)) {
553
+ if (!moment(month, 'MMMM').isValid()) {
554
+ return;
555
+ }
556
+ returnValue = parseInt(moment().month(month).format('M'), 10);
557
+ }
558
+ else {
559
+ returnValue = monthAsNumber;
560
+ }
561
+ // Ensure that the month is between 1 and 12
562
+ if (!(1 <= returnValue && returnValue <= 12)) {
563
+ return;
564
+ }
565
+ return returnValue;
566
+ }
567
+ getDefaultYear(fuzzyDate) {
568
+ // Check if we need to return a leap year or the current year.
569
+ if (fuzzyDate.month === 2 && fuzzyDate.day === 29) {
570
+ return this.getMostRecentLeapYear();
571
+ }
572
+ else {
573
+ return new Date().getFullYear();
574
+ }
575
+ }
576
+ getDateComponents(date) {
577
+ const separator = this.getDateSeparator(date);
578
+ return date.split(separator);
579
+ }
580
+ // Returns the order of year, month, and day from the provided date format.
581
+ getDateFormatIndexes(dateFormat) {
582
+ dateFormat = dateFormat.toLowerCase();
583
+ return {
584
+ yearIndex: dateFormat.indexOf('y'),
585
+ monthIndex: dateFormat.indexOf('m'),
586
+ dayIndex: dateFormat.indexOf('d'),
587
+ };
588
+ }
589
+ // Returns the index of each of the date components in the provided string (month, day, year).
590
+ getDateValueIndexes(date, dateFormat) {
591
+ const dateFormatIndexes = this.getDateFormatIndexes(dateFormat);
592
+ const dateComponentIndexes = [];
593
+ if (dateFormatIndexes.yearIndex > -1) {
594
+ dateComponentIndexes.push(dateFormatIndexes.yearIndex);
595
+ }
596
+ if (dateFormatIndexes.monthIndex > -1) {
597
+ dateComponentIndexes.push(dateFormatIndexes.monthIndex);
598
+ }
599
+ if (dateFormatIndexes.dayIndex > -1) {
600
+ dateComponentIndexes.push(dateFormatIndexes.dayIndex);
601
+ }
602
+ dateComponentIndexes.sort(function (a, b) {
603
+ return a - b;
604
+ });
605
+ return {
606
+ yearIndex: dateComponentIndexes.indexOf(dateFormatIndexes.yearIndex),
607
+ monthIndex: dateComponentIndexes.indexOf(dateFormatIndexes.monthIndex),
608
+ dayIndex: dateComponentIndexes.indexOf(dateFormatIndexes.dayIndex),
609
+ };
610
+ }
611
+ /**
612
+ * Validates the provided SkyFuzzyDate object. Valid fuzzy dates are as follows:
613
+ * month, day, year
614
+ * month, year
615
+ * month, day
616
+ * year only
617
+ */
618
+ isFuzzyDateValid(fuzzyDate) {
619
+ if (!fuzzyDate) {
620
+ return false;
621
+ }
622
+ // If none of the dates part are specified, return false.
623
+ if (!fuzzyDate.day && !fuzzyDate.month && !fuzzyDate.year) {
624
+ return false;
625
+ }
626
+ // If only month is specified, return false.
627
+ if (!fuzzyDate.day && fuzzyDate.month && !fuzzyDate.year) {
628
+ return false;
629
+ }
630
+ // If only day is specified, return false.
631
+ if (fuzzyDate.day && !fuzzyDate.month && !fuzzyDate.year) {
632
+ return false;
633
+ }
634
+ return true;
635
+ }
636
+ }
637
+ SkyFuzzyDateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyFuzzyDateService, deps: [{ token: i3.SkyAppLocaleProvider }], target: i0.ɵɵFactoryTarget.Injectable });
638
+ SkyFuzzyDateService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyFuzzyDateService, providedIn: 'root' });
639
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyFuzzyDateService, decorators: [{
640
+ type: Injectable,
641
+ args: [{
642
+ providedIn: 'root',
643
+ }]
644
+ }], ctorParameters: function () { return [{ type: i3.SkyAppLocaleProvider }]; } });
645
+
646
+ /**
647
+ * Formats date values using two or more date tokens that represent the day, month,
648
+ * and year. The tokens are described in the [moment.js values](https://momentjs.com/docs/#/displaying/).
649
+ * @example
650
+ * ```markup
651
+ * {{ myFuzzyDate | skyFuzzyDate:'MMM Y' }}
652
+ * {{ myFuzzyDate | skyFuzzyDate:'MMM Y':'en-CA' }}
653
+ * ```
654
+ */
655
+ class SkyFuzzyDatePipe {
656
+ constructor(fuzzyDateService) {
657
+ this.fuzzyDateService = fuzzyDateService;
658
+ }
659
+ /**
660
+ * Transforms fuzzy date values using two or more date tokens that represent the day, month,
661
+ * and year.
662
+ * @param value Specifies the date value to transform.
663
+ * @param format Specifies the format to apply to the transform. You construct the format
664
+ * string with a two or more tokens that specify the components of date-time value. The
665
+ * tokens are described in the [moment.js values](https://momentjs.com/docs/#/displaying/).
666
+ * If you don't provide a format, `SkyFuzzyDatePipe` attempts to format fuzzy dates based
667
+ * on the browser's default locale.
668
+ * @param locale Specifies the locale code to use in the transform.
669
+ */
670
+ transform(value, format, locale) {
671
+ if (!value) {
672
+ return undefined;
673
+ }
674
+ const fuzzyDateFormat = format || this.fuzzyDateService.getLocaleShortFormat(locale);
675
+ const fuzzyDateLocale = locale || this.fuzzyDateService.getCurrentLocale();
676
+ return this.fuzzyDateService.format(value, fuzzyDateFormat, fuzzyDateLocale);
677
+ }
678
+ }
679
+ SkyFuzzyDatePipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyFuzzyDatePipe, deps: [{ token: SkyFuzzyDateService }], target: i0.ɵɵFactoryTarget.Pipe });
680
+ SkyFuzzyDatePipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyFuzzyDatePipe, name: "skyFuzzyDate", pure: false });
681
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyFuzzyDatePipe, decorators: [{
682
+ type: Pipe,
683
+ args: [{
684
+ name: 'skyFuzzyDate',
685
+ pure: false,
686
+ }]
687
+ }], ctorParameters: function () { return [{ type: SkyFuzzyDateService }]; } });
688
+
689
+ class SkyDatePipeModule {
690
+ }
691
+ SkyDatePipeModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatePipeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
692
+ SkyDatePipeModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatePipeModule, declarations: [SkyDatePipe, SkyFuzzyDatePipe], imports: [CommonModule, SkyDatetimeResourcesModule], exports: [SkyDatePipe, SkyFuzzyDatePipe] });
693
+ SkyDatePipeModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatePipeModule, providers: [SkyDatePipe, SkyFuzzyDatePipe], imports: [[CommonModule, SkyDatetimeResourcesModule]] });
694
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatePipeModule, decorators: [{
695
+ type: NgModule,
696
+ args: [{
697
+ declarations: [SkyDatePipe, SkyFuzzyDatePipe],
698
+ providers: [SkyDatePipe, SkyFuzzyDatePipe],
699
+ imports: [CommonModule, SkyDatetimeResourcesModule],
700
+ exports: [SkyDatePipe, SkyFuzzyDatePipe],
701
+ }]
702
+ }] });
703
+
704
+ /**
705
+ * Represents the calculator.
706
+ */
707
+ class SkyDateRangeCalculator {
708
+ constructor(
709
+ /**
710
+ * Provides a calculator ID to specify calculator objects that represent date ranges.
711
+ */
712
+ calculatorId, config) {
713
+ this.calculatorId = calculatorId;
714
+ this.config = config;
715
+ this.type = config.type;
716
+ this.shortDescription = config.shortDescription;
717
+ }
718
+ /**
719
+ * Gets the current value of the calculator.
720
+ * @param startDateInput The start date.
721
+ * @param endDateInput The end date.
722
+ */
723
+ getValue(startDateInput, endDateInput) {
724
+ const result = this.config.getValue(startDateInput, endDateInput);
725
+ /* tslint:disable:no-null-keyword */
726
+ // (Angular form controls use null for the "empty" value.)
727
+ let startDate = null;
728
+ if (result.startDate instanceof Date) {
729
+ startDate = this.parseDateWithoutTime(result.startDate);
730
+ }
731
+ let endDate = null;
732
+ if (result.endDate instanceof Date) {
733
+ endDate = this.parseDateWithoutTime(result.endDate);
734
+ }
735
+ /* tslint:enable */
736
+ return {
737
+ calculatorId: this.calculatorId,
738
+ startDate,
739
+ endDate,
740
+ };
741
+ }
742
+ /**
743
+ * Performs synchronous validation against the control.
744
+ */
745
+ validate(value) {
746
+ if (!this.config.validate) {
747
+ return;
748
+ }
749
+ return this.config.validate(value);
750
+ }
751
+ /**
752
+ * Get a date object without time information.
753
+ * See: https://stackoverflow.com/a/38050824/6178885
754
+ */
755
+ parseDateWithoutTime(date) {
756
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
757
+ }
758
+ }
759
+
760
+ /**
761
+ * `SkyDateRangeCalculatorId` values specify calculator objects that return
762
+ * two `Date` objects to represent date ranges. The values populate the options
763
+ * in the date range picker's dropdown. SKY UX uses `SkyDateRangeService` to create
764
+ * calculators and configures each one with a `validate` function to confirm that dates
765
+ * are compatible. For example, `validate` functions ensure that start dates are before
766
+ * end dates. SKY UX also configures calculators to call a `getValue` function after
767
+ * the `validate` function and return a range of two `Date` objects.
768
+ */
769
+ var SkyDateRangeCalculatorId;
770
+ (function (SkyDateRangeCalculatorId) {
771
+ /**
772
+ * Selects no dates and considers all dates within the date range. This is the default selection.
773
+ */
774
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["AnyTime"] = 0] = "AnyTime";
775
+ /**
776
+ * Enables users to select an end date with no starting date.
777
+ */
778
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["Before"] = 1] = "Before";
779
+ /**
780
+ * Enables users to select a start date with no end date.
781
+ */
782
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["After"] = 2] = "After";
783
+ /**
784
+ * Enables users to select specific start and end dates.
785
+ */
786
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["SpecificRange"] = 3] = "SpecificRange";
787
+ /**
788
+ * Sets the start and end dates to the day before the current day.
789
+ */
790
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["Yesterday"] = 4] = "Yesterday";
791
+ /**
792
+ * Sets the start and end dates to the current day.
793
+ */
794
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["Today"] = 5] = "Today";
795
+ /**
796
+ * Sets the start and end dates to the day after the current day.
797
+ */
798
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["Tomorrow"] = 6] = "Tomorrow";
799
+ /**
800
+ * Sets the start date to Sunday of the week before the current week and
801
+ * the end date to Saturday of that week.
802
+ */
803
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["LastWeek"] = 7] = "LastWeek";
804
+ /**
805
+ * Sets the start date to Sunday of the current week and the end date to Saturday.
806
+ */
807
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["ThisWeek"] = 8] = "ThisWeek";
808
+ /**
809
+ * Sets the start date to Sunday of the week after the current week and
810
+ * the end date to Saturday of that week.
811
+ */
812
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["NextWeek"] = 9] = "NextWeek";
813
+ /**
814
+ * Sets the start date to the first day of the month before the current month and
815
+ * the end date to the last day of that month.
816
+ */
817
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["LastMonth"] = 10] = "LastMonth";
818
+ /**
819
+ * Sets the start date to the first day of the current month and
820
+ * the end date to the last day of the month.
821
+ */
822
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["ThisMonth"] = 11] = "ThisMonth";
823
+ /**
824
+ * Sets the start date to the first day of the month after the current month
825
+ * and the end date to the last day of that month.
826
+ */
827
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["NextMonth"] = 12] = "NextMonth";
828
+ /**
829
+ * Sets the start date to the first day of the quarter before the current quarter and
830
+ * the end date to the last day of that quarter. Quarters are
831
+ * January to March, April to June, July to September, and October to December.
832
+ */
833
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["LastQuarter"] = 13] = "LastQuarter";
834
+ /**
835
+ * Sets the start date to the first day of the current quarter and
836
+ * the end date to the last day of the quarter. Quarters are
837
+ * January to March, April to June, July to September, and October to December.
838
+ */
839
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["ThisQuarter"] = 14] = "ThisQuarter";
840
+ /**
841
+ * Sets the start date to the first day of the quarter after the current quarter and
842
+ * the end date to the last day of that quarter. Quarters are
843
+ * January to March, April to June, July to September, and October to December.
844
+ */
845
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["NextQuarter"] = 15] = "NextQuarter";
846
+ /**
847
+ * Sets the start date to the first day of the year before the current year
848
+ * and the end date to the last day of that year.
849
+ */
850
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["LastCalendarYear"] = 16] = "LastCalendarYear";
851
+ /**
852
+ * Sets the start date to the first day of the current year and
853
+ * the end date to the last day of the year.
854
+ */
855
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["ThisCalendarYear"] = 17] = "ThisCalendarYear";
856
+ /**
857
+ * Sets the start date to the first day of the year after the current year and
858
+ * the end date to the last day of that year.
859
+ */
860
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["NextCalendarYear"] = 18] = "NextCalendarYear";
861
+ /**
862
+ * Sets the start date to the first day of the fiscal year before the current fiscal year and
863
+ * the end date to the last day of that fiscal year. The fiscal year is Oct. 1 to Sept. 30.
864
+ */
865
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["LastFiscalYear"] = 19] = "LastFiscalYear";
866
+ /**
867
+ * Sets the start date to the first day of the current fiscal year and
868
+ * the end date to the last day of the fiscal year. The fiscal year is Oct. 1 to Sept. 30.
869
+ */
870
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["ThisFiscalYear"] = 20] = "ThisFiscalYear";
871
+ /**
872
+ * Sets the start date to the first day of the fiscal year after the current fiscal year
873
+ * and the end date to the last day of that fiscal year. The fiscal year is Oct. 1 to Sept. 30.
874
+ */
875
+ SkyDateRangeCalculatorId[SkyDateRangeCalculatorId["NextFiscalYear"] = 21] = "NextFiscalYear";
876
+ })(SkyDateRangeCalculatorId || (SkyDateRangeCalculatorId = {}));
877
+
878
+ /**
879
+ * Indicates the types of calculations available for a date range calculator.
880
+ */
881
+ var SkyDateRangeCalculatorType;
882
+ (function (SkyDateRangeCalculatorType) {
883
+ /**
884
+ * Includes an input for a date after the current date.
885
+ */
886
+ SkyDateRangeCalculatorType[SkyDateRangeCalculatorType["After"] = 0] = "After";
887
+ /**
888
+ * Includes an input for a date before the current date.
889
+ */
890
+ SkyDateRangeCalculatorType[SkyDateRangeCalculatorType["Before"] = 1] = "Before";
891
+ /**
892
+ * Includes two inputs for a range of dates.
893
+ */
894
+ SkyDateRangeCalculatorType[SkyDateRangeCalculatorType["Range"] = 2] = "Range";
895
+ /**
896
+ * Does not accept any input but calculates a specific range based on the current date.
897
+ */
898
+ SkyDateRangeCalculatorType[SkyDateRangeCalculatorType["Relative"] = 3] = "Relative";
899
+ })(SkyDateRangeCalculatorType || (SkyDateRangeCalculatorType = {}));
900
+
901
+ class SkyDateFormatter {
902
+ /**
903
+ * Sets moment's global locale.
904
+ */
905
+ static setLocale(locale) {
906
+ moment.locale(locale || SkyDateFormatter.defaultLocale);
907
+ }
908
+ /**
909
+ * Returns the preferred short date format for the current locale.
910
+ */
911
+ static getPreferredShortDateFormat() {
912
+ /* istanbul ignore next */
913
+ return (moment.localeData().longDateFormat('L') ||
914
+ SkyDateFormatter.defaultShortDateFormat);
915
+ }
916
+ format(date, format) {
917
+ return moment(date.getTime()).format(format);
918
+ }
919
+ getDateFromString(dateString, format,
920
+ /* istanbul ignore next */
921
+ strict = false) {
922
+ let momentValue = moment(dateString, format, strict);
923
+ if (!momentValue.isValid()) {
924
+ momentValue = moment(dateString, 'YYYY-MM-DDThh:mm:ss.SZ', strict);
925
+ }
926
+ return momentValue.toDate();
927
+ }
928
+ dateIsValid(date) {
929
+ return (date &&
930
+ date instanceof Date &&
931
+ !isNaN(date.valueOf()) &&
932
+ !isNaN(new Date(date).getDate()));
933
+ }
934
+ }
935
+ SkyDateFormatter.defaultLocale = 'en-US';
936
+ SkyDateFormatter.defaultShortDateFormat = 'MM/DD/YYYY';
937
+
938
+ let nextDatepickerId = 0;
939
+ /**
940
+ * @internal
941
+ */
942
+ class SkyDatepickerCalendarInnerComponent {
943
+ constructor() {
944
+ this.selectedDateChange = new EventEmitter(undefined);
945
+ this.calendarModeChange = new EventEmitter();
946
+ this.minMode = 'day';
947
+ this.maxMode = 'year';
948
+ this.monthColLimit = 3;
949
+ this.yearColLimit = 5;
950
+ this.datepickerMode = 'day';
951
+ this.yearRange = 20;
952
+ this.formatDay = 'DD';
953
+ this.formatMonth = 'MMMM';
954
+ this.formatYear = 'YYYY';
955
+ this.formatDayHeader = 'dd';
956
+ this.formatDayTitle = 'MMMM YYYY';
957
+ this.formatMonthTitle = 'YYYY';
958
+ this.datepickerId = `sky-datepicker-${++nextDatepickerId}`;
959
+ this.stepDay = {};
960
+ this.stepMonth = {};
961
+ this.stepYear = {};
962
+ this.modes = ['day', 'month', 'year'];
963
+ this.dateFormatter = new SkyDateFormatter();
964
+ this.keys = {
965
+ 13: 'enter',
966
+ 32: 'space',
967
+ 33: 'pageup',
968
+ 34: 'pagedown',
969
+ 35: 'end',
970
+ 36: 'home',
971
+ 37: 'left',
972
+ 38: 'up',
973
+ 39: 'right',
974
+ 40: 'down',
975
+ };
976
+ this.ngUnsubscribe = new Subject();
977
+ }
978
+ set selectedDate(value) {
979
+ if (this.dateFormatter.dateIsValid(value)) {
980
+ this._selectedDate = value;
981
+ this.activeDate = value;
982
+ }
983
+ }
984
+ get selectedDate() {
985
+ return this._selectedDate;
986
+ }
987
+ ngOnInit() {
988
+ if (this.selectedDate) {
989
+ this.activeDate = new Date(this.selectedDate);
990
+ }
991
+ else {
992
+ this.activeDate = new Date();
993
+ }
994
+ }
995
+ ngOnChanges(changes) {
996
+ this.refreshView();
997
+ }
998
+ ngOnDestroy() {
999
+ this.ngUnsubscribe.next();
1000
+ this.ngUnsubscribe.complete();
1001
+ }
1002
+ setCompareHandler(handler, type) {
1003
+ if (type === 'day') {
1004
+ this.compareHandlerDay = handler;
1005
+ }
1006
+ if (type === 'month') {
1007
+ this.compareHandlerMonth = handler;
1008
+ }
1009
+ if (type === 'year') {
1010
+ this.compareHandlerYear = handler;
1011
+ }
1012
+ }
1013
+ compare(date1, date2) {
1014
+ if (date1 === undefined || date2 === undefined) {
1015
+ return undefined;
1016
+ }
1017
+ if (this.datepickerMode === 'day' && this.compareHandlerDay) {
1018
+ return this.compareHandlerDay(date1, date2);
1019
+ }
1020
+ if (this.datepickerMode === 'month' && this.compareHandlerMonth) {
1021
+ return this.compareHandlerMonth(date1, date2);
1022
+ }
1023
+ /* istanbul ignore else */
1024
+ /* sanity check */
1025
+ if (this.datepickerMode === 'year' && this.compareHandlerYear) {
1026
+ return this.compareHandlerYear(date1, date2);
1027
+ }
1028
+ }
1029
+ setRefreshViewHandler(handler, type) {
1030
+ if (type === 'day') {
1031
+ this.refreshViewHandlerDay = handler;
1032
+ }
1033
+ if (type === 'month') {
1034
+ this.refreshViewHandlerMonth = handler;
1035
+ }
1036
+ if (type === 'year') {
1037
+ this.refreshViewHandlerYear = handler;
1038
+ }
1039
+ }
1040
+ refreshView() {
1041
+ if (this.datepickerMode === 'day' && this.refreshViewHandlerDay) {
1042
+ this.refreshViewHandlerDay();
1043
+ }
1044
+ if (this.datepickerMode === 'month' && this.refreshViewHandlerMonth) {
1045
+ this.refreshViewHandlerMonth();
1046
+ }
1047
+ if (this.datepickerMode === 'year' && this.refreshViewHandlerYear) {
1048
+ this.refreshViewHandlerYear();
1049
+ }
1050
+ }
1051
+ setKeydownHandler(handler, type) {
1052
+ if (type === 'day') {
1053
+ this.handleKeydownDay = handler;
1054
+ }
1055
+ if (type === 'month') {
1056
+ this.handleKeydownMonth = handler;
1057
+ }
1058
+ if (type === 'year') {
1059
+ this.handleKeydownYear = handler;
1060
+ }
1061
+ }
1062
+ handleKeydown(key, event) {
1063
+ if (this.datepickerMode === 'day' && this.handleKeydownDay) {
1064
+ this.handleKeydownDay(key, event);
1065
+ }
1066
+ if (this.datepickerMode === 'month' && this.handleKeydownMonth) {
1067
+ this.handleKeydownMonth(key, event);
1068
+ }
1069
+ if (this.datepickerMode === 'year' && this.handleKeydownYear) {
1070
+ this.handleKeydownYear(key, event);
1071
+ }
1072
+ }
1073
+ dateFilter(date, format) {
1074
+ return this.dateFormatter.format(date, format);
1075
+ }
1076
+ isActive(dateObject) {
1077
+ if (this.compare(dateObject.date, this.activeDate) === 0) {
1078
+ this.activeDateId = dateObject.uid;
1079
+ return true;
1080
+ }
1081
+ return false;
1082
+ }
1083
+ onKeydown(event) {
1084
+ const key = this.keys[event.which];
1085
+ if (!key || event.shiftKey || event.altKey) {
1086
+ return;
1087
+ }
1088
+ event.preventDefault();
1089
+ event.stopPropagation();
1090
+ if (key === 'enter' || key === 'space') {
1091
+ if (this.isDisabled(this.activeDate)) {
1092
+ return;
1093
+ }
1094
+ this.select(this.activeDate);
1095
+ }
1096
+ else if (event.ctrlKey && (key === 'up' || key === 'down')) {
1097
+ this.toggleMode(key === 'up' ? 1 : -1);
1098
+ }
1099
+ else {
1100
+ this.handleKeydown(key, event);
1101
+ this.refreshView();
1102
+ }
1103
+ }
1104
+ createDateObject(date, format, isSecondary, id) {
1105
+ const customDateMatch = this.getCustomDate(date);
1106
+ const dateObject = {
1107
+ date: new Date(date.getFullYear(), date.getMonth(), date.getDate()),
1108
+ label: this.dateFilter(date, format),
1109
+ selected: this.compare(date, this.selectedDate) === 0,
1110
+ disabled: this.isDisabled(date),
1111
+ current: this.compare(date, new Date()) === 0,
1112
+ secondary: isSecondary,
1113
+ uid: id,
1114
+ keyDate: customDateMatch ? customDateMatch.keyDate : undefined,
1115
+ keyDateText: customDateMatch ? customDateMatch.keyDateText : [],
1116
+ };
1117
+ return dateObject;
1118
+ }
1119
+ createCalendarRows(dates, size) {
1120
+ const rows = [];
1121
+ while (dates.length > 0) {
1122
+ rows.push(dates.splice(0, size));
1123
+ }
1124
+ return rows;
1125
+ }
1126
+ /*
1127
+ This is ensures that no strangeness happens when converting a date to local time.
1128
+ */
1129
+ fixTimeZone(date) {
1130
+ const newDate = new Date(date);
1131
+ newDate.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
1132
+ return newDate;
1133
+ }
1134
+ selectCalendar(event, date, closePicker = false) {
1135
+ if (!closePicker) {
1136
+ event.preventDefault();
1137
+ event.stopPropagation();
1138
+ }
1139
+ this.select(date);
1140
+ }
1141
+ select(date, isManual = true) {
1142
+ this.activeDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
1143
+ /*
1144
+ Only actually select date if in minmode (day picker mode).
1145
+ Otherwise, just change the active view for the datepicker.
1146
+ */
1147
+ if (this.datepickerMode === this.minMode) {
1148
+ this.selectedDate = new Date(this.activeDate);
1149
+ if (isManual) {
1150
+ this.selectedDateChange.emit(this.selectedDate);
1151
+ }
1152
+ }
1153
+ else {
1154
+ this.datepickerMode =
1155
+ this.modes[this.modes.indexOf(this.datepickerMode) - 1];
1156
+ this.calendarModeChange.emit(this.datepickerMode);
1157
+ }
1158
+ this.refreshView();
1159
+ }
1160
+ moveCalendar(event, direction) {
1161
+ event.preventDefault();
1162
+ event.stopPropagation();
1163
+ this.move(direction);
1164
+ }
1165
+ move(direction) {
1166
+ let expectedStep;
1167
+ if (this.datepickerMode === 'day') {
1168
+ expectedStep = this.stepDay;
1169
+ }
1170
+ if (this.datepickerMode === 'month') {
1171
+ expectedStep = this.stepMonth;
1172
+ }
1173
+ if (this.datepickerMode === 'year') {
1174
+ expectedStep = this.stepYear;
1175
+ }
1176
+ /* istanbul ignore else */
1177
+ /* sanity check */
1178
+ if (expectedStep) {
1179
+ const year = this.activeDate.getFullYear() + direction * (expectedStep.years || 0);
1180
+ const month = this.activeDate.getMonth() + direction * (expectedStep.months || 0);
1181
+ this.activeDate = new Date(year, month, 1);
1182
+ this.refreshView();
1183
+ }
1184
+ }
1185
+ toggleModeCalendar(event) {
1186
+ event.preventDefault();
1187
+ event.stopPropagation();
1188
+ this.toggleMode(1);
1189
+ }
1190
+ toggleMode(direction) {
1191
+ /*istanbul ignore next */
1192
+ direction = direction || 1;
1193
+ /* istanbul ignore else */
1194
+ /* sanity check */
1195
+ if (!(direction === 1 && this.datepickerMode === this.maxMode) &&
1196
+ !(this.datepickerMode === this.minMode && direction === -1)) {
1197
+ this.datepickerMode =
1198
+ this.modes[this.modes.indexOf(this.datepickerMode) + direction];
1199
+ this.calendarModeChange.emit(this.datepickerMode);
1200
+ this.refreshView();
1201
+ }
1202
+ }
1203
+ /**
1204
+ * Date is disabled if it meets any of these criteria:
1205
+ * 1. Date falls outside the min or max dates set by the SkyDatepickerConfigService.
1206
+ * 2. Date is marked as disabled in the customDates array.
1207
+ */
1208
+ isDisabled(date) {
1209
+ const customDate = this.getCustomDate(date);
1210
+ return ((this.minDate && this.compare(date, this.minDate) < 0) ||
1211
+ (this.maxDate && this.compare(date, this.maxDate) > 0) ||
1212
+ (customDate && customDate.disabled));
1213
+ }
1214
+ getCustomDate(date) {
1215
+ if (this.customDates) {
1216
+ return this.customDates.find((customDate) => {
1217
+ return customDate.date.getTime() === date.getTime();
1218
+ });
1219
+ }
1220
+ }
1221
+ }
1222
+ SkyDatepickerCalendarInnerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerCalendarInnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1223
+ SkyDatepickerCalendarInnerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: SkyDatepickerCalendarInnerComponent, selector: "sky-datepicker-inner", inputs: { customDates: "customDates", startingDay: "startingDay", minDate: "minDate", maxDate: "maxDate", selectedDate: "selectedDate" }, outputs: { selectedDateChange: "selectedDateChange", calendarModeChange: "calendarModeChange" }, usesOnChanges: true, ngImport: i0, template: "<div\n *ngIf=\"datepickerMode\"\n class=\"sky-datepicker-calendar-inner\"\n (keydown)=\"onKeydown($event)\"\n>\n <ng-content></ng-content>\n</div>\n", styles: [".sky-datepicker-calendar-inner{border-radius:5px;background-color:#fff;border-top:1px solid #e2e3e4;border-bottom:1px solid #e2e3e4;border-left:1px solid #e2e3e4;border-right:1px solid #e2e3e4}.sky-datepicker-calendar-inner .sky-btn-default{border-color:transparent;border:2px solid #ffffff}.sky-datepicker-calendar-inner .sky-btn-default:hover{border-color:#eeeeef}.sky-datepicker-calendar-inner .sky-datepicker-center{text-align:center}.sky-datepicker-calendar-inner .sky-datepicker-btn-selected,.sky-datepicker-calendar-inner .sky-btn-default.sky-datepicker-btn-selected:hover{background-color:#c1e8fb;border:2px solid #00b4f1}.sky-datepicker-calendar-inner .sky-btn.sky-btn-active{box-shadow:none}.sky-datepicker-calendar-inner .sky-datepicker-secondary{color:#686c73}.sky-datepicker-calendar-inner .sky-datepicker-btn-date{min-width:100%}.sky-datepicker-calendar-inner .sky-datepicker-calendar-title{width:100%}.sky-datepicker-calendar-inner .sky-datepicker-chevron-modern{display:none}.sky-datepicker-calendar-inner .sky-datepicker-header-left{text-align:left}.sky-datepicker-calendar-inner .sky-datepicker-header-right{text-align:right}.sky-theme-modern .sky-datepicker-calendar-inner{border:none;box-shadow:inset 0 0 0 1px #d2d2d2;border-radius:6px;padding:5px 10px}.sky-theme-modern .sky-datepicker-calendar-inner:focus-within{border:none;box-shadow:inset 0 0 0 2px #1870b8,0 1px 3px #0000004d}.sky-theme-modern .sky-datepicker-calendar-inner .sky-btn-default{border:none;box-shadow:inset 0 0 0 1px transparent;padding:5px 7px}.sky-theme-modern .sky-datepicker-calendar-inner .sky-btn-active,.sky-theme-modern .sky-datepicker-calendar-inner .sky-btn-default:hover{border:none;box-shadow:inset 0 0 0 1px #1870b8}.sky-theme-modern .sky-btn-sm.sky-datepicker-btn-date{height:30px;min-width:0;padding:0;width:30px}.sky-theme-modern .sky-datepicker-chevron-default{display:none}.sky-theme-modern .sky-datepicker-chevron-modern{display:inline;font-size:16px}.sky-theme-modern.sky-theme-mode-dark .sky-datepicker-calendar-inner{background-color:transparent}.sky-theme-modern.sky-theme-mode-dark .sky-datepicker-calendar-inner:not(:focus-within){border:none;box-shadow:inset 0 0 0 1px #686c73}.sky-theme-modern.sky-theme-mode-dark .sky-datepicker-calendar-inner .sky-datepicker-btn-selected{background-color:#009cd1}\n"], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], encapsulation: i0.ViewEncapsulation.None });
1224
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerCalendarInnerComponent, decorators: [{
1225
+ type: Component,
1226
+ args: [{ selector: 'sky-datepicker-inner', encapsulation: ViewEncapsulation.None, template: "<div\n *ngIf=\"datepickerMode\"\n class=\"sky-datepicker-calendar-inner\"\n (keydown)=\"onKeydown($event)\"\n>\n <ng-content></ng-content>\n</div>\n", styles: [".sky-datepicker-calendar-inner{border-radius:5px;background-color:#fff;border-top:1px solid #e2e3e4;border-bottom:1px solid #e2e3e4;border-left:1px solid #e2e3e4;border-right:1px solid #e2e3e4}.sky-datepicker-calendar-inner .sky-btn-default{border-color:transparent;border:2px solid #ffffff}.sky-datepicker-calendar-inner .sky-btn-default:hover{border-color:#eeeeef}.sky-datepicker-calendar-inner .sky-datepicker-center{text-align:center}.sky-datepicker-calendar-inner .sky-datepicker-btn-selected,.sky-datepicker-calendar-inner .sky-btn-default.sky-datepicker-btn-selected:hover{background-color:#c1e8fb;border:2px solid #00b4f1}.sky-datepicker-calendar-inner .sky-btn.sky-btn-active{box-shadow:none}.sky-datepicker-calendar-inner .sky-datepicker-secondary{color:#686c73}.sky-datepicker-calendar-inner .sky-datepicker-btn-date{min-width:100%}.sky-datepicker-calendar-inner .sky-datepicker-calendar-title{width:100%}.sky-datepicker-calendar-inner .sky-datepicker-chevron-modern{display:none}.sky-datepicker-calendar-inner .sky-datepicker-header-left{text-align:left}.sky-datepicker-calendar-inner .sky-datepicker-header-right{text-align:right}.sky-theme-modern .sky-datepicker-calendar-inner{border:none;box-shadow:inset 0 0 0 1px #d2d2d2;border-radius:6px;padding:5px 10px}.sky-theme-modern .sky-datepicker-calendar-inner:focus-within{border:none;box-shadow:inset 0 0 0 2px #1870b8,0 1px 3px #0000004d}.sky-theme-modern .sky-datepicker-calendar-inner .sky-btn-default{border:none;box-shadow:inset 0 0 0 1px transparent;padding:5px 7px}.sky-theme-modern .sky-datepicker-calendar-inner .sky-btn-active,.sky-theme-modern .sky-datepicker-calendar-inner .sky-btn-default:hover{border:none;box-shadow:inset 0 0 0 1px #1870b8}.sky-theme-modern .sky-btn-sm.sky-datepicker-btn-date{height:30px;min-width:0;padding:0;width:30px}.sky-theme-modern .sky-datepicker-chevron-default{display:none}.sky-theme-modern .sky-datepicker-chevron-modern{display:inline;font-size:16px}.sky-theme-modern.sky-theme-mode-dark .sky-datepicker-calendar-inner{background-color:transparent}.sky-theme-modern.sky-theme-mode-dark .sky-datepicker-calendar-inner:not(:focus-within){border:none;box-shadow:inset 0 0 0 1px #686c73}.sky-theme-modern.sky-theme-mode-dark .sky-datepicker-calendar-inner .sky-datepicker-btn-selected{background-color:#009cd1}\n"] }]
1227
+ }], propDecorators: { customDates: [{
1228
+ type: Input
1229
+ }], startingDay: [{
1230
+ type: Input
1231
+ }], minDate: [{
1232
+ type: Input
1233
+ }], maxDate: [{
1234
+ type: Input
1235
+ }], selectedDate: [{
1236
+ type: Input
1237
+ }], selectedDateChange: [{
1238
+ type: Output
1239
+ }], calendarModeChange: [{
1240
+ type: Output
1241
+ }] } });
1242
+
1243
+ /**
1244
+ * @internal
1245
+ */
1246
+ class SkyDatepickerAdapterService {
1247
+ constructor(renderer) {
1248
+ this.renderer = renderer;
1249
+ }
1250
+ init(elRef) {
1251
+ this.el = elRef.nativeElement;
1252
+ }
1253
+ elementIsFocused() {
1254
+ const focusedEl = document.activeElement;
1255
+ return this.el.contains(focusedEl);
1256
+ }
1257
+ elementIsVisible() {
1258
+ const styles = this.el && getComputedStyle(this.el);
1259
+ return styles && styles.visibility === 'visible';
1260
+ }
1261
+ getPlaceholder(elementRef) {
1262
+ return elementRef.nativeElement.getAttribute('placeholder');
1263
+ }
1264
+ setPlaceholder(elementRef, value) {
1265
+ this.renderer.setAttribute(elementRef.nativeElement, 'placeholder', value);
1266
+ }
1267
+ }
1268
+ SkyDatepickerAdapterService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerAdapterService, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Injectable });
1269
+ SkyDatepickerAdapterService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerAdapterService });
1270
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerAdapterService, decorators: [{
1271
+ type: Injectable
1272
+ }], ctorParameters: function () { return [{ type: i0.Renderer2 }]; } });
1273
+
1274
+ class SkyDatepickerConfigService {
1275
+ constructor() {
1276
+ /**
1277
+ * Specifies the starting day of the week in the calendar,
1278
+ * where `0` sets the starting day to Sunday.
1279
+ * @default 0
1280
+ */
1281
+ this.startingDay = 0;
1282
+ }
1283
+ }
1284
+ SkyDatepickerConfigService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerConfigService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1285
+ SkyDatepickerConfigService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerConfigService, providedIn: 'root' });
1286
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerConfigService, decorators: [{
1287
+ type: Injectable,
1288
+ args: [{
1289
+ providedIn: 'root',
1290
+ }]
1291
+ }] });
1292
+
1293
+ /**
1294
+ * @internal
1295
+ */
1296
+ class SkyDatepickerService {
1297
+ constructor() {
1298
+ /**
1299
+ * Specifies if a key date popover is currently displayed.
1300
+ * Useful for communicating across all daypicker siblings when a popover is displayed.
1301
+ */
1302
+ this.keyDatePopoverStream = new Subject();
1303
+ }
1304
+ }
1305
+ SkyDatepickerService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1306
+ SkyDatepickerService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerService });
1307
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerService, decorators: [{
1308
+ type: Injectable
1309
+ }] });
1310
+
1311
+ /**
1312
+ * @internal
1313
+ */
1314
+ class SkyDayPickerButtonComponent {
1315
+ constructor(datepicker) {
1316
+ this.datepicker = datepicker;
1317
+ }
1318
+ }
1319
+ SkyDayPickerButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDayPickerButtonComponent, deps: [{ token: SkyDatepickerCalendarInnerComponent }], target: i0.ɵɵFactoryTarget.Component });
1320
+ SkyDayPickerButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: SkyDayPickerButtonComponent, selector: "sky-daypicker-button", inputs: { date: "date" }, ngImport: i0, template: "<button\n class=\"sky-btn sky-btn-sm sky-btn-default sky-datepicker-btn-date\"\n tabindex=\"-1\"\n type=\"button\"\n [disabled]=\"date.disabled\"\n [ngClass]=\"{\n 'sky-datepicker-btn-selected': date.selected,\n 'sky-btn-disabled': date.disabled,\n 'sky-btn-active': datepicker.isActive(date),\n 'sky-datepicker-btn-disabled': date.disabled,\n 'sky-datepicker-btn-key-date': date.keyDate\n }\"\n (click)=\"datepicker.selectCalendar($event, date.date, true)\"\n>\n <span [ngClass]=\"{ 'sky-datepicker-secondary': date.secondary }\">\n {{ date.label }}\n </span>\n</button>\n", styles: [".sky-datepicker-btn-disabled{font-style:italic}.sky-datepicker-btn-key-date{position:relative}.sky-datepicker-btn-key-date:before{position:absolute;content:\"\";height:5px;width:5px;background-color:#d93a3d;border-radius:50%;left:15px;top:22px}:host-context(.sky-theme-modern) .sky-datepicker-btn-key-date:before{left:12px}.sky-theme-modern .sky-datepicker-btn-key-date:before{left:12px}\n"], directives: [{ type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] });
1321
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDayPickerButtonComponent, decorators: [{
1322
+ type: Component,
1323
+ args: [{ selector: 'sky-daypicker-button', template: "<button\n class=\"sky-btn sky-btn-sm sky-btn-default sky-datepicker-btn-date\"\n tabindex=\"-1\"\n type=\"button\"\n [disabled]=\"date.disabled\"\n [ngClass]=\"{\n 'sky-datepicker-btn-selected': date.selected,\n 'sky-btn-disabled': date.disabled,\n 'sky-btn-active': datepicker.isActive(date),\n 'sky-datepicker-btn-disabled': date.disabled,\n 'sky-datepicker-btn-key-date': date.keyDate\n }\"\n (click)=\"datepicker.selectCalendar($event, date.date, true)\"\n>\n <span [ngClass]=\"{ 'sky-datepicker-secondary': date.secondary }\">\n {{ date.label }}\n </span>\n</button>\n", styles: [".sky-datepicker-btn-disabled{font-style:italic}.sky-datepicker-btn-key-date{position:relative}.sky-datepicker-btn-key-date:before{position:absolute;content:\"\";height:5px;width:5px;background-color:#d93a3d;border-radius:50%;left:15px;top:22px}:host-context(.sky-theme-modern) .sky-datepicker-btn-key-date:before{left:12px}.sky-theme-modern .sky-datepicker-btn-key-date:before{left:12px}\n"] }]
1324
+ }], ctorParameters: function () { return [{ type: SkyDatepickerCalendarInnerComponent }]; }, propDecorators: { date: [{
1325
+ type: Input
1326
+ }] } });
1327
+
1328
+ /**
1329
+ * @internal
1330
+ */
1331
+ class SkyDayPickerCellComponent {
1332
+ constructor(datepicker, datepickerService) {
1333
+ this.datepicker = datepicker;
1334
+ this.datepickerService = datepickerService;
1335
+ this.hasTooltip = false;
1336
+ this.popoverController = new Subject();
1337
+ this.activeUid = '';
1338
+ this.cancelPopover = false;
1339
+ this.popoverOpen = false;
1340
+ this.ngUnsubscribe = new Subject();
1341
+ }
1342
+ ngOnInit() {
1343
+ this.hasTooltip =
1344
+ this.date.keyDate &&
1345
+ this.date.keyDateText &&
1346
+ this.date.keyDateText.length > 0 &&
1347
+ this.date.keyDateText[0].length > 0;
1348
+ // show the tooltip if this is the active date and is not the
1349
+ // initial active date (activeDateHasChanged)
1350
+ if (this.datepicker.isActive(this.date) &&
1351
+ this.activeDateHasChanged &&
1352
+ this.hasTooltip) {
1353
+ this.activeUid = this.date.uid;
1354
+ this.showTooltip();
1355
+ }
1356
+ if (this.hasTooltip) {
1357
+ this.datepickerService.keyDatePopoverStream
1358
+ .pipe(takeUntil(this.ngUnsubscribe))
1359
+ .subscribe((date) => {
1360
+ if (date) {
1361
+ this.activeUid = date.uid;
1362
+ }
1363
+ else {
1364
+ this.activeUid = '';
1365
+ }
1366
+ // If this day has an open popover and they have moved off of the day close the popover.
1367
+ if (this.date.uid !== this.activeUid) {
1368
+ this.hideTooltip();
1369
+ }
1370
+ });
1371
+ }
1372
+ }
1373
+ ngOnDestroy() {
1374
+ this.ngUnsubscribe.next();
1375
+ this.ngUnsubscribe.complete();
1376
+ }
1377
+ onDayMouseenter() {
1378
+ this.cancelPopover = false;
1379
+ if (this.hasTooltip) {
1380
+ this.showTooltip();
1381
+ this.datepickerService.keyDatePopoverStream.next(this.date);
1382
+ }
1383
+ }
1384
+ onDayMouseleave() {
1385
+ this.cancelPopover = true;
1386
+ if (this.hasTooltip) {
1387
+ this.hideTooltip();
1388
+ }
1389
+ this.datepickerService.keyDatePopoverStream.next(undefined);
1390
+ }
1391
+ onPopoverClosed() {
1392
+ this.popoverOpen = false;
1393
+ }
1394
+ onPopoverOpened() {
1395
+ this.popoverOpen = true;
1396
+ /* istanbul ignore else */
1397
+ if (this.cancelPopover) {
1398
+ // If the popover gets opened just as a mouseout event happens, close it.
1399
+ this.hideTooltip();
1400
+ this.cancelPopover = false;
1401
+ }
1402
+ }
1403
+ getKeyDateLabel() {
1404
+ if (this.hasTooltip) {
1405
+ return this.date.keyDateText.join(', ');
1406
+ }
1407
+ else {
1408
+ return '';
1409
+ }
1410
+ }
1411
+ hideTooltip() {
1412
+ /* istanbul ignore else */
1413
+ if (this.popoverOpen) {
1414
+ this.popoverController.next({ type: SkyPopoverMessageType.Close });
1415
+ }
1416
+ }
1417
+ showTooltip() {
1418
+ /* istanbul ignore else */
1419
+ if (this.hasTooltip && !this.popoverOpen) {
1420
+ /**
1421
+ * Delay 1/2 second before opening the popover as long as mouse hasn't moved off the date.
1422
+ */
1423
+ setTimeout(() => {
1424
+ if (!this.cancelPopover && this.activeUid === this.date.uid) {
1425
+ this.popoverController.next({ type: SkyPopoverMessageType.Open });
1426
+ }
1427
+ }, 500);
1428
+ }
1429
+ }
1430
+ }
1431
+ SkyDayPickerCellComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDayPickerCellComponent, deps: [{ token: SkyDatepickerCalendarInnerComponent }, { token: SkyDatepickerService }], target: i0.ɵɵFactoryTarget.Component });
1432
+ SkyDayPickerCellComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: SkyDayPickerCellComponent, selector: "sky-daypicker-cell", inputs: { activeDateHasChanged: "activeDateHasChanged", date: "date" }, ngImport: i0, template: "<div\n *ngIf=\"hasTooltip\"\n class=\"sky-daypicker-cell\"\n [attr.aria-label]=\"getKeyDateLabel()\"\n [skyPopover]=\"dayInfoPopover\"\n skyPopoverPlacement=\"left\"\n [skyPopoverMessageStream]=\"popoverController\"\n (mouseenter)=\"onDayMouseenter()\"\n (mouseleave)=\"onDayMouseleave()\"\n>\n <ng-container *ngTemplateOutlet=\"daypickerButtonTemplateRef\"></ng-container>\n <sky-popover\n (popoverClosed)=\"onPopoverClosed()\"\n (popoverOpened)=\"onPopoverOpened()\"\n #dayInfoPopover\n >\n <div *ngFor=\"let text of date.keyDateText\">\n {{ text }}\n </div>\n </sky-popover>\n</div>\n<div\n *ngIf=\"!hasTooltip\"\n class=\"sky-daypicker-cell\"\n (mouseenter)=\"onDayMouseenter()\"\n (mouseleave)=\"onDayMouseleave()\"\n>\n <ng-container *ngTemplateOutlet=\"daypickerButtonTemplateRef\"></ng-container>\n</div>\n\n<ng-template #daypickerButtonTemplateRef>\n <sky-daypicker-button [date]=\"date\"> </sky-daypicker-button>\n</ng-template>\n", components: [{ type: i3$1.λ6, selector: "sky-popover", inputs: ["alignment", "dismissOnBlur", "placement", "popoverTitle", "popoverType"], outputs: ["popoverClosed", "popoverOpened"] }, { type: SkyDayPickerButtonComponent, selector: "sky-daypicker-button", inputs: ["date"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3$1.λ7, selector: "[skyPopover]", inputs: ["skyPopover", "skyPopoverAlignment", "skyPopoverMessageStream", "skyPopoverPlacement", "skyPopoverTrigger"] }, { type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1433
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDayPickerCellComponent, decorators: [{
1434
+ type: Component,
1435
+ args: [{ selector: 'sky-daypicker-cell', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n *ngIf=\"hasTooltip\"\n class=\"sky-daypicker-cell\"\n [attr.aria-label]=\"getKeyDateLabel()\"\n [skyPopover]=\"dayInfoPopover\"\n skyPopoverPlacement=\"left\"\n [skyPopoverMessageStream]=\"popoverController\"\n (mouseenter)=\"onDayMouseenter()\"\n (mouseleave)=\"onDayMouseleave()\"\n>\n <ng-container *ngTemplateOutlet=\"daypickerButtonTemplateRef\"></ng-container>\n <sky-popover\n (popoverClosed)=\"onPopoverClosed()\"\n (popoverOpened)=\"onPopoverOpened()\"\n #dayInfoPopover\n >\n <div *ngFor=\"let text of date.keyDateText\">\n {{ text }}\n </div>\n </sky-popover>\n</div>\n<div\n *ngIf=\"!hasTooltip\"\n class=\"sky-daypicker-cell\"\n (mouseenter)=\"onDayMouseenter()\"\n (mouseleave)=\"onDayMouseleave()\"\n>\n <ng-container *ngTemplateOutlet=\"daypickerButtonTemplateRef\"></ng-container>\n</div>\n\n<ng-template #daypickerButtonTemplateRef>\n <sky-daypicker-button [date]=\"date\"> </sky-daypicker-button>\n</ng-template>\n" }]
1436
+ }], ctorParameters: function () { return [{ type: SkyDatepickerCalendarInnerComponent }, { type: SkyDatepickerService }]; }, propDecorators: { activeDateHasChanged: [{
1437
+ type: Input
1438
+ }], date: [{
1439
+ type: Input
1440
+ }] } });
1441
+
1442
+ /**
1443
+ * @internal
1444
+ */
1445
+ class SkyDayPickerComponent {
1446
+ constructor(datepicker) {
1447
+ this.calendarDateRangeChange = new EventEmitter();
1448
+ this.isWaiting = false;
1449
+ this.activeDateHasChanged = false;
1450
+ this.labels = [];
1451
+ this.rows = [];
1452
+ this.weekNumbers = [];
1453
+ this.daysInMonth = [
1454
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
1455
+ ];
1456
+ this.ngUnsubscribe = new Subject();
1457
+ this.datepicker = datepicker;
1458
+ }
1459
+ set customDates(value) {
1460
+ /* istanbul ignore else */
1461
+ if (value) {
1462
+ this.applyCustomDates(value, this.rows);
1463
+ }
1464
+ }
1465
+ ngOnInit() {
1466
+ this.datepicker.stepDay = { months: 1 };
1467
+ this.initialDate = this.datepicker.activeDate.getDate();
1468
+ this.datepicker.setRefreshViewHandler(() => {
1469
+ this.refreshDayView();
1470
+ }, 'day');
1471
+ this.datepicker.setCompareHandler(this.compareDays, 'day');
1472
+ this.datepicker.setKeydownHandler((key, event) => {
1473
+ this.keydownDays(key, event);
1474
+ }, 'day');
1475
+ this.datepicker.refreshView();
1476
+ }
1477
+ ngOnDestroy() {
1478
+ this.ngUnsubscribe.next();
1479
+ this.ngUnsubscribe.complete();
1480
+ }
1481
+ getDates(startDate, n) {
1482
+ const dates = new Array(n);
1483
+ let current = new Date(startDate.getTime());
1484
+ let i = 0;
1485
+ let date;
1486
+ while (i < n) {
1487
+ date = new Date(current.getTime());
1488
+ date = this.datepicker.fixTimeZone(date);
1489
+ dates[i++] = date;
1490
+ current = new Date(current.getFullYear(), current.getMonth(), current.getDate() + 1);
1491
+ }
1492
+ return dates;
1493
+ }
1494
+ compareDays(date1, date2) {
1495
+ const d1 = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
1496
+ const d2 = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());
1497
+ return d1.getTime() - d2.getTime();
1498
+ }
1499
+ refreshDayView() {
1500
+ const year = this.datepicker.activeDate.getFullYear();
1501
+ const month = this.datepicker.activeDate.getMonth();
1502
+ const firstDayOfMonth = new Date(year, month, 1);
1503
+ const difference = this.datepicker.startingDay - firstDayOfMonth.getDay();
1504
+ const numDisplayedFromPreviousMonth = difference > 0 ? 7 - difference : -difference;
1505
+ const firstDate = new Date(firstDayOfMonth.getTime());
1506
+ if (this.datepicker.activeDate.getDate() !== this.initialDate) {
1507
+ this.activeDateHasChanged = true;
1508
+ }
1509
+ /* istanbul ignore else */
1510
+ /* sanity check */
1511
+ if (numDisplayedFromPreviousMonth > 0) {
1512
+ firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
1513
+ }
1514
+ // 42 is the number of days on a six-week calendar
1515
+ const days = this.getDates(firstDate, 42);
1516
+ const pickerDates = [];
1517
+ for (let i = 0; i < 42; i++) {
1518
+ const _dateObject = this.datepicker.createDateObject(days[i], this.datepicker.formatDay, days[i].getMonth() !== month, this.datepicker.datepickerId + '-' + i);
1519
+ pickerDates[i] = _dateObject;
1520
+ }
1521
+ this.labels = [];
1522
+ for (let j = 0; j < 7; j++) {
1523
+ this.labels[j] = {};
1524
+ this.labels[j].abbr = this.datepicker.dateFilter(pickerDates[j].date, this.datepicker.formatDayHeader);
1525
+ this.labels[j].full = this.datepicker.dateFilter(pickerDates[j].date, 'EEEE');
1526
+ }
1527
+ this.title = this.datepicker.dateFilter(this.datepicker.activeDate, this.datepicker.formatDayTitle);
1528
+ const oldDateRange = this.getDateRange(this.rows);
1529
+ this.rows = this.datepicker.createCalendarRows(pickerDates, 7);
1530
+ const newDateRange = this.getDateRange(this.rows);
1531
+ if (!this.dateRangeRowsAreEqual(oldDateRange, newDateRange)) {
1532
+ this.calendarDateRangeChange.next({
1533
+ startDate: newDateRange.startDate,
1534
+ endDate: newDateRange.endDate,
1535
+ });
1536
+ }
1537
+ }
1538
+ keydownDays(key, event) {
1539
+ let date = this.datepicker.activeDate.getDate();
1540
+ /* istanbul ignore else */
1541
+ /* sanity check */
1542
+ if (key === 'left') {
1543
+ date = date - 1;
1544
+ }
1545
+ else if (key === 'up') {
1546
+ date = date - 7;
1547
+ }
1548
+ else if (key === 'right') {
1549
+ date = date + 1;
1550
+ }
1551
+ else if (key === 'down') {
1552
+ date = date + 7;
1553
+ }
1554
+ else if (key === 'pageup' || key === 'pagedown') {
1555
+ const month = this.datepicker.activeDate.getMonth() + (key === 'pageup' ? -1 : 1);
1556
+ this.datepicker.activeDate.setMonth(month, 1);
1557
+ date = Math.min(this.getDaysInMonth(this.datepicker.activeDate.getFullYear(), this.datepicker.activeDate.getMonth()), date);
1558
+ }
1559
+ else if (key === 'home') {
1560
+ date = 1;
1561
+ }
1562
+ else if (key === 'end') {
1563
+ date = this.getDaysInMonth(this.datepicker.activeDate.getFullYear(), this.datepicker.activeDate.getMonth());
1564
+ }
1565
+ this.datepicker.activeDate.setDate(date);
1566
+ }
1567
+ getDaysInMonth(year, month) {
1568
+ return month === 1 &&
1569
+ year % 4 === 0 &&
1570
+ (year % 400 === 0 || year % 100 !== 0)
1571
+ ? 29
1572
+ : this.daysInMonth[month];
1573
+ }
1574
+ /**
1575
+ * Applies custom date properties to the existing dates displayed in the calendar.
1576
+ */
1577
+ applyCustomDates(customDates, dateRows) {
1578
+ let date;
1579
+ let newDate;
1580
+ let dateIndex;
1581
+ /* istanbul ignore else */
1582
+ if (customDates && dateRows) {
1583
+ customDates.forEach((customDate) => {
1584
+ dateIndex = -1;
1585
+ dateRows.forEach((row) => {
1586
+ if (dateIndex === -1) {
1587
+ dateIndex = row.findIndex((d) => {
1588
+ return d.date.getTime() === customDate.date.getTime();
1589
+ });
1590
+ if (dateIndex > -1) {
1591
+ date = row[dateIndex];
1592
+ // Replace the date with a new instance so the display gets updated.
1593
+ newDate = {
1594
+ current: date.current,
1595
+ date: date.date,
1596
+ disabled: !!date.disabled || !!customDate.disabled,
1597
+ keyDate: !!customDate.keyDate || !!date.keyDate,
1598
+ keyDateText: customDate.keyDateText || date.keyDateText,
1599
+ label: date.label,
1600
+ secondary: date.secondary,
1601
+ selected: date.selected,
1602
+ uid: date.uid,
1603
+ };
1604
+ row[dateIndex] = newDate;
1605
+ }
1606
+ }
1607
+ });
1608
+ });
1609
+ }
1610
+ }
1611
+ dateRangeRowsAreEqual(rangeA, rangeB) {
1612
+ /* istanbul ignore if */
1613
+ if (!rangeA && !rangeB) {
1614
+ return true;
1615
+ }
1616
+ else if ((rangeA && !rangeB) || (!rangeA && rangeB)) {
1617
+ return false;
1618
+ }
1619
+ return (this.compareDays(rangeA.startDate, rangeB.startDate) === 0 &&
1620
+ this.compareDays(rangeA.endDate, rangeB.endDate) === 0);
1621
+ }
1622
+ getDateRange(rows) {
1623
+ /* istanbul ignore else */
1624
+ if (rows && rows.length > 0) {
1625
+ return {
1626
+ startDate: rows[0][0].date,
1627
+ endDate: rows[rows.length - 1][rows[rows.length - 1].length - 1].date,
1628
+ };
1629
+ }
1630
+ }
1631
+ }
1632
+ SkyDayPickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDayPickerComponent, deps: [{ token: SkyDatepickerCalendarInnerComponent }], target: i0.ɵɵFactoryTarget.Component });
1633
+ SkyDayPickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: SkyDayPickerComponent, selector: "sky-daypicker", inputs: { customDates: "customDates", isWaiting: "isWaiting" }, outputs: { calendarDateRangeChange: "calendarDateRangeChange" }, ngImport: i0, template: "<div *ngIf=\"datepicker.datepickerMode === 'day'\" class=\"sky-daypicker-wrapper\">\n <table\n class=\"sky-daypicker-table\"\n role=\"grid\"\n [attr.aria-labelledby]=\"datepicker.datepickerId + '-title'\"\n >\n <thead>\n <tr>\n <th class=\"sky-datepicker-header-left\" scope=\"col\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-btn-previous\"\n (click)=\"datepicker.moveCalendar($event, -1)\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n >\n <sky-icon\n class=\"sky-datepicker-chevron-default\"\n icon=\"chevron-left\"\n ></sky-icon>\n <sky-icon\n class=\"sky-datepicker-chevron-modern\"\n icon=\"chevron-left\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </th>\n <th scope=\"col\" [attr.colspan]=\"5\">\n <button\n [id]=\"datepicker.datepickerId + '-title'\"\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-calendar-title\"\n (click)=\"datepicker.toggleModeCalendar($event)\"\n [disabled]=\"datepicker.datepickerMode === datepicker.maxMode\"\n [ngClass]=\"{\n 'sky-btn-disabled':\n datepicker.datepickerMode === datepicker.maxMode\n }\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n >\n <strong>{{ title }}</strong>\n </button>\n </th>\n <th class=\"sky-datepicker-header-right\" scope=\"col\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-btn-next\"\n (click)=\"datepicker.moveCalendar($event, 1)\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n >\n <sky-icon\n class=\"sky-datepicker-chevron-default\"\n icon=\"chevron-right\"\n ></sky-icon>\n <sky-icon\n class=\"sky-datepicker-chevron-modern\"\n icon=\"chevron-right\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </th>\n </tr>\n <tr>\n <th\n scope=\"col\"\n *ngFor=\"let label of labels\"\n class=\"sky-datepicker-center sky-datepicker-weekdays\"\n >\n <small [attr.aria-label]=\"label.full\">\n <b>{{ label.abbr }}</b>\n </small>\n </th>\n </tr>\n </thead>\n <tbody>\n <!-- Wait indicator for async custom date stream -->\n <sky-wait [isWaiting]=\"isWaiting\"> </sky-wait>\n <ng-template ngFor [ngForOf]=\"rows\" let-row=\"$implicit\" let-index=\"index\">\n <tr role=\"row\">\n <td\n *ngFor=\"let date of row\"\n class=\"sky-datepicker-center\"\n role=\"gridcell\"\n [id]=\"date.uid\"\n >\n <sky-daypicker-cell\n [activeDateHasChanged]=\"activeDateHasChanged\"\n [date]=\"date\"\n >\n </sky-daypicker-cell>\n </td>\n </tr>\n </ng-template>\n </tbody>\n </table>\n</div>\n", styles: [":host-context(.sky-theme-modern) :host:focus{outline:none}.sky-theme-modern :host:focus{outline:none}\n"], components: [{ type: i2.λ4, selector: "sky-icon", inputs: ["icon", "iconType", "size", "fixedWidth", "variant"] }, { type: i2.λ14, selector: "sky-wait", inputs: ["ariaLabel", "isWaiting", "isFullPage", "isNonBlocking"] }, { type: SkyDayPickerCellComponent, selector: "sky-daypicker-cell", inputs: ["activeDateHasChanged", "date"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
1634
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDayPickerComponent, decorators: [{
1635
+ type: Component,
1636
+ args: [{ selector: 'sky-daypicker', template: "<div *ngIf=\"datepicker.datepickerMode === 'day'\" class=\"sky-daypicker-wrapper\">\n <table\n class=\"sky-daypicker-table\"\n role=\"grid\"\n [attr.aria-labelledby]=\"datepicker.datepickerId + '-title'\"\n >\n <thead>\n <tr>\n <th class=\"sky-datepicker-header-left\" scope=\"col\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-btn-previous\"\n (click)=\"datepicker.moveCalendar($event, -1)\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n >\n <sky-icon\n class=\"sky-datepicker-chevron-default\"\n icon=\"chevron-left\"\n ></sky-icon>\n <sky-icon\n class=\"sky-datepicker-chevron-modern\"\n icon=\"chevron-left\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </th>\n <th scope=\"col\" [attr.colspan]=\"5\">\n <button\n [id]=\"datepicker.datepickerId + '-title'\"\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-calendar-title\"\n (click)=\"datepicker.toggleModeCalendar($event)\"\n [disabled]=\"datepicker.datepickerMode === datepicker.maxMode\"\n [ngClass]=\"{\n 'sky-btn-disabled':\n datepicker.datepickerMode === datepicker.maxMode\n }\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n >\n <strong>{{ title }}</strong>\n </button>\n </th>\n <th class=\"sky-datepicker-header-right\" scope=\"col\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-btn-next\"\n (click)=\"datepicker.moveCalendar($event, 1)\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n >\n <sky-icon\n class=\"sky-datepicker-chevron-default\"\n icon=\"chevron-right\"\n ></sky-icon>\n <sky-icon\n class=\"sky-datepicker-chevron-modern\"\n icon=\"chevron-right\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </th>\n </tr>\n <tr>\n <th\n scope=\"col\"\n *ngFor=\"let label of labels\"\n class=\"sky-datepicker-center sky-datepicker-weekdays\"\n >\n <small [attr.aria-label]=\"label.full\">\n <b>{{ label.abbr }}</b>\n </small>\n </th>\n </tr>\n </thead>\n <tbody>\n <!-- Wait indicator for async custom date stream -->\n <sky-wait [isWaiting]=\"isWaiting\"> </sky-wait>\n <ng-template ngFor [ngForOf]=\"rows\" let-row=\"$implicit\" let-index=\"index\">\n <tr role=\"row\">\n <td\n *ngFor=\"let date of row\"\n class=\"sky-datepicker-center\"\n role=\"gridcell\"\n [id]=\"date.uid\"\n >\n <sky-daypicker-cell\n [activeDateHasChanged]=\"activeDateHasChanged\"\n [date]=\"date\"\n >\n </sky-daypicker-cell>\n </td>\n </tr>\n </ng-template>\n </tbody>\n </table>\n</div>\n", styles: [":host-context(.sky-theme-modern) :host:focus{outline:none}.sky-theme-modern :host:focus{outline:none}\n"] }]
1637
+ }], ctorParameters: function () { return [{ type: SkyDatepickerCalendarInnerComponent }]; }, propDecorators: { customDates: [{
1638
+ type: Input
1639
+ }], calendarDateRangeChange: [{
1640
+ type: Output
1641
+ }], isWaiting: [{
1642
+ type: Input
1643
+ }] } });
1644
+
1645
+ /**
1646
+ * @internal
1647
+ */
1648
+ class SkyMonthPickerComponent {
1649
+ constructor(datepicker) {
1650
+ this.rows = [];
1651
+ this.datepicker = datepicker;
1652
+ }
1653
+ ngOnInit() {
1654
+ this.datepicker.stepMonth = {
1655
+ years: 1,
1656
+ };
1657
+ this.datepicker.setRefreshViewHandler(() => {
1658
+ this.refreshMonthView();
1659
+ }, 'month');
1660
+ this.datepicker.setCompareHandler(this.compareMonth, 'month');
1661
+ this.datepicker.refreshView();
1662
+ this.datepicker.setKeydownHandler((key, event) => {
1663
+ this.keydownMonths(key, event);
1664
+ }, 'month');
1665
+ }
1666
+ compareMonth(date1, date2) {
1667
+ const d1 = new Date(date1.getFullYear(), date1.getMonth());
1668
+ const d2 = new Date(date2.getFullYear(), date2.getMonth());
1669
+ return d1.getTime() - d2.getTime();
1670
+ }
1671
+ refreshMonthView() {
1672
+ const months = new Array(12);
1673
+ const year = this.datepicker.activeDate.getFullYear();
1674
+ let date;
1675
+ for (let i = 0; i < 12; i++) {
1676
+ date = new Date(year, i, 1);
1677
+ date = this.datepicker.fixTimeZone(date);
1678
+ months[i] = this.datepicker.createDateObject(date, this.datepicker.formatMonth, false, this.datepicker.datepickerId + '-' + i);
1679
+ }
1680
+ this.title = this.datepicker.dateFilter(this.datepicker.activeDate, this.datepicker.formatMonthTitle);
1681
+ this.rows = this.datepicker.createCalendarRows(months, this.datepicker.monthColLimit);
1682
+ }
1683
+ keydownMonths(key, event) {
1684
+ let date = this.datepicker.activeDate.getMonth();
1685
+ /* istanbul ignore else */
1686
+ /* sanity check */
1687
+ if (key === 'left') {
1688
+ date = date - 1;
1689
+ }
1690
+ else if (key === 'up') {
1691
+ date = date - this.datepicker.monthColLimit;
1692
+ }
1693
+ else if (key === 'right') {
1694
+ date = date + 1;
1695
+ }
1696
+ else if (key === 'down') {
1697
+ date = date + this.datepicker.monthColLimit;
1698
+ }
1699
+ else if (key === 'pageup' || key === 'pagedown') {
1700
+ const year = this.datepicker.activeDate.getFullYear() + (key === 'pageup' ? -1 : 1);
1701
+ this.datepicker.activeDate.setFullYear(year);
1702
+ }
1703
+ else if (key === 'home') {
1704
+ date = 0;
1705
+ }
1706
+ else if (key === 'end') {
1707
+ date = 11;
1708
+ }
1709
+ this.datepicker.activeDate.setMonth(date);
1710
+ }
1711
+ }
1712
+ SkyMonthPickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyMonthPickerComponent, deps: [{ token: SkyDatepickerCalendarInnerComponent }], target: i0.ɵɵFactoryTarget.Component });
1713
+ SkyMonthPickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: SkyMonthPickerComponent, selector: "sky-monthpicker", ngImport: i0, template: "<table *ngIf=\"datepicker.datepickerMode === 'month'\" role=\"grid\">\n <thead>\n <tr>\n <th class=\"sky-datepicker-header-left\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-btn-previous\"\n (click)=\"datepicker.moveCalendar($event, -1)\"\n tabindex=\"-1\"\n >\n <sky-icon\n class=\"sky-datepicker-chevron-default\"\n icon=\"chevron-left\"\n ></sky-icon>\n <sky-icon\n class=\"sky-datepicker-chevron-modern\"\n icon=\"chevron-left\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </th>\n <th\n [attr.colspan]=\"\n datepicker.monthColLimit - 2 <= 0 ? 1 : datepicker.monthColLimit - 2\n \"\n >\n <button\n [id]=\"datepicker.datepickerId + '-title'\"\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-calendar-title\"\n (click)=\"datepicker.toggleModeCalendar($event)\"\n [disabled]=\"datepicker.datepickerMode === maxMode\"\n [ngClass]=\"{\n 'sky-btn-disabled': datepicker.datepickerMode === maxMode\n }\"\n tabindex=\"-1\"\n >\n <strong>{{ title }}</strong>\n </button>\n </th>\n <th class=\"sky-datepicker-header-right\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-btn-next\"\n (click)=\"datepicker.moveCalendar($event, 1)\"\n tabindex=\"-1\"\n >\n <sky-icon\n class=\"sky-datepicker-chevron-default\"\n icon=\"chevron-right\"\n ></sky-icon>\n <sky-icon\n class=\"sky-datepicker-chevron-modern\"\n icon=\"chevron-right\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of rows\">\n <td\n *ngFor=\"let date of row\"\n class=\"text-center\"\n role=\"gridcell\"\n id=\"{{ date.uid }}\"\n >\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-datepicker-btn-date\"\n [ngClass]=\"{\n 'sky-datepicker-btn-selected': date.selected,\n 'sky-btn-disabled': date.disabled,\n 'sky-btn-active': datepicker.isActive(date)\n }\"\n [disabled]=\"date.disabled\"\n (click)=\"datepicker.selectCalendar($event, date.date)\"\n tabindex=\"-1\"\n >\n <span [ngClass]=\"{ 'sky-datepicker-current': date.current }\">{{\n date.label\n }}</span>\n </button>\n </td>\n </tr>\n </tbody>\n</table>\n", styles: [":host-context(.sky-theme-modern) :host:focus{outline:none}.sky-theme-modern :host:focus{outline:none}\n"], components: [{ type: i2.λ4, selector: "sky-icon", inputs: ["icon", "iconType", "size", "fixedWidth", "variant"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
1714
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyMonthPickerComponent, decorators: [{
1715
+ type: Component,
1716
+ args: [{ selector: 'sky-monthpicker', template: "<table *ngIf=\"datepicker.datepickerMode === 'month'\" role=\"grid\">\n <thead>\n <tr>\n <th class=\"sky-datepicker-header-left\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-btn-previous\"\n (click)=\"datepicker.moveCalendar($event, -1)\"\n tabindex=\"-1\"\n >\n <sky-icon\n class=\"sky-datepicker-chevron-default\"\n icon=\"chevron-left\"\n ></sky-icon>\n <sky-icon\n class=\"sky-datepicker-chevron-modern\"\n icon=\"chevron-left\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </th>\n <th\n [attr.colspan]=\"\n datepicker.monthColLimit - 2 <= 0 ? 1 : datepicker.monthColLimit - 2\n \"\n >\n <button\n [id]=\"datepicker.datepickerId + '-title'\"\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-calendar-title\"\n (click)=\"datepicker.toggleModeCalendar($event)\"\n [disabled]=\"datepicker.datepickerMode === maxMode\"\n [ngClass]=\"{\n 'sky-btn-disabled': datepicker.datepickerMode === maxMode\n }\"\n tabindex=\"-1\"\n >\n <strong>{{ title }}</strong>\n </button>\n </th>\n <th class=\"sky-datepicker-header-right\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-btn-next\"\n (click)=\"datepicker.moveCalendar($event, 1)\"\n tabindex=\"-1\"\n >\n <sky-icon\n class=\"sky-datepicker-chevron-default\"\n icon=\"chevron-right\"\n ></sky-icon>\n <sky-icon\n class=\"sky-datepicker-chevron-modern\"\n icon=\"chevron-right\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of rows\">\n <td\n *ngFor=\"let date of row\"\n class=\"text-center\"\n role=\"gridcell\"\n id=\"{{ date.uid }}\"\n >\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-datepicker-btn-date\"\n [ngClass]=\"{\n 'sky-datepicker-btn-selected': date.selected,\n 'sky-btn-disabled': date.disabled,\n 'sky-btn-active': datepicker.isActive(date)\n }\"\n [disabled]=\"date.disabled\"\n (click)=\"datepicker.selectCalendar($event, date.date)\"\n tabindex=\"-1\"\n >\n <span [ngClass]=\"{ 'sky-datepicker-current': date.current }\">{{\n date.label\n }}</span>\n </button>\n </td>\n </tr>\n </tbody>\n</table>\n", styles: [":host-context(.sky-theme-modern) :host:focus{outline:none}.sky-theme-modern :host:focus{outline:none}\n"] }]
1717
+ }], ctorParameters: function () { return [{ type: SkyDatepickerCalendarInnerComponent }]; } });
1718
+
1719
+ /**
1720
+ * @internal
1721
+ */
1722
+ class SkyYearPickerComponent {
1723
+ constructor(datepicker) {
1724
+ this.rows = [];
1725
+ this.datepicker = datepicker;
1726
+ }
1727
+ ngOnInit() {
1728
+ this.datepicker.stepYear = { years: this.datepicker.yearRange };
1729
+ this.datepicker.setRefreshViewHandler(() => {
1730
+ this.refreshYearView();
1731
+ }, 'year');
1732
+ this.datepicker.setCompareHandler(this.compareYears, 'year');
1733
+ this.datepicker.setKeydownHandler((key, event) => {
1734
+ this.keydownYears(key, event);
1735
+ }, 'year');
1736
+ this.datepicker.refreshView();
1737
+ }
1738
+ getStartingYear(year) {
1739
+ return (Math.floor((year - 1) / this.datepicker.yearRange) *
1740
+ this.datepicker.yearRange +
1741
+ 1);
1742
+ }
1743
+ compareYears(date1, date2) {
1744
+ return date1.getFullYear() - date2.getFullYear();
1745
+ }
1746
+ refreshYearView() {
1747
+ const years = new Array(this.datepicker.yearRange);
1748
+ let date;
1749
+ const start = this.getStartingYear(this.datepicker.activeDate.getFullYear());
1750
+ for (let i = 0; i < this.datepicker.yearRange; i++) {
1751
+ date = new Date(this.datepicker.activeDate);
1752
+ date.setFullYear(start + i, 0, 1);
1753
+ years[i] = this.datepicker.createDateObject(date, this.datepicker.formatYear, false, this.datepicker.datepickerId + '-' + i);
1754
+ }
1755
+ this.title = [
1756
+ years[0].label,
1757
+ years[this.datepicker.yearRange - 1].label,
1758
+ ].join(' - ');
1759
+ this.rows = this.datepicker.createCalendarRows(years, this.datepicker.yearColLimit);
1760
+ }
1761
+ keydownYears(key, event) {
1762
+ let date = this.datepicker.activeDate.getFullYear();
1763
+ /* istanbul ignore else */
1764
+ /* sanity check */
1765
+ if (key === 'left') {
1766
+ date = date - 1;
1767
+ }
1768
+ else if (key === 'up') {
1769
+ date = date - this.datepicker.yearColLimit;
1770
+ }
1771
+ else if (key === 'right') {
1772
+ date = date + 1;
1773
+ }
1774
+ else if (key === 'down') {
1775
+ date = date + this.datepicker.yearColLimit;
1776
+ }
1777
+ else if (key === 'pageup' || key === 'pagedown') {
1778
+ date += (key === 'pageup' ? -1 : 1) * this.datepicker.yearRange;
1779
+ }
1780
+ else if (key === 'home') {
1781
+ date = this.getStartingYear(this.datepicker.activeDate.getFullYear());
1782
+ }
1783
+ else if (key === 'end') {
1784
+ date =
1785
+ this.getStartingYear(this.datepicker.activeDate.getFullYear()) +
1786
+ this.datepicker.yearRange -
1787
+ 1;
1788
+ }
1789
+ this.datepicker.activeDate.setFullYear(date);
1790
+ }
1791
+ }
1792
+ SkyYearPickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyYearPickerComponent, deps: [{ token: SkyDatepickerCalendarInnerComponent }], target: i0.ɵɵFactoryTarget.Component });
1793
+ SkyYearPickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: SkyYearPickerComponent, selector: "sky-yearpicker", ngImport: i0, template: "<table *ngIf=\"datepicker.datepickerMode === 'year'\" role=\"grid\">\n <thead>\n <tr>\n <th class=\"sky-datepicker-header-left\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-btn-previous\"\n (click)=\"datepicker.moveCalendar($event, -1)\"\n tabindex=\"-1\"\n >\n <sky-icon\n class=\"sky-datepicker-chevron-default\"\n icon=\"chevron-left\"\n ></sky-icon>\n <sky-icon\n class=\"sky-datepicker-chevron-modern\"\n icon=\"chevron-left\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </th>\n <th\n [attr.colspan]=\"\n datepicker.yearColLimit - 2 <= 0 ? 1 : datepicker.yearColLimit - 2\n \"\n >\n <button\n [id]=\"datepicker.datepickerId + '-title'\"\n role=\"heading\"\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-calendar-title\"\n (click)=\"datepicker.toggleModeCalendar($event)\"\n [disabled]=\"datepicker.datepickerMode === datepicker.maxMode\"\n [ngClass]=\"{\n 'sky-btn-disabled': datepicker.datepickerMode === datepicker.maxMode\n }\"\n tabindex=\"-1\"\n >\n <strong>{{ title }}</strong>\n </button>\n </th>\n <th class=\"sky-datepicker-header-right\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-btn-next\"\n (click)=\"datepicker.moveCalendar($event, 1)\"\n tabindex=\"-1\"\n >\n <sky-icon\n class=\"sky-datepicker-chevron-default\"\n icon=\"chevron-right\"\n ></sky-icon>\n <sky-icon\n class=\"sky-datepicker-chevron-modern\"\n icon=\"chevron-right\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of rows\">\n <td *ngFor=\"let date of row\" class=\"sky-datepicker-row\" role=\"gridcell\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-datepicker-btn-date\"\n [ngClass]=\"{\n 'sky-datepicker-btn-selected': date.selected,\n 'sky-btn-disabled': date.disabled,\n 'sky-btn-active': datepicker.isActive(date)\n }\"\n [disabled]=\"date.disabled\"\n (click)=\"datepicker.selectCalendar($event, date.date)\"\n tabindex=\"-1\"\n >\n <span [ngClass]=\"{ 'sky-datepicker-current': date.current }\">{{\n date.label\n }}</span>\n </button>\n </td>\n </tr>\n </tbody>\n</table>\n", styles: [":host-context(.sky-theme-modern) :host:focus{outline:none}.sky-theme-modern :host:focus{outline:none}\n"], components: [{ type: i2.λ4, selector: "sky-icon", inputs: ["icon", "iconType", "size", "fixedWidth", "variant"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
1794
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyYearPickerComponent, decorators: [{
1795
+ type: Component,
1796
+ args: [{ selector: 'sky-yearpicker', template: "<table *ngIf=\"datepicker.datepickerMode === 'year'\" role=\"grid\">\n <thead>\n <tr>\n <th class=\"sky-datepicker-header-left\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-btn-previous\"\n (click)=\"datepicker.moveCalendar($event, -1)\"\n tabindex=\"-1\"\n >\n <sky-icon\n class=\"sky-datepicker-chevron-default\"\n icon=\"chevron-left\"\n ></sky-icon>\n <sky-icon\n class=\"sky-datepicker-chevron-modern\"\n icon=\"chevron-left\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </th>\n <th\n [attr.colspan]=\"\n datepicker.yearColLimit - 2 <= 0 ? 1 : datepicker.yearColLimit - 2\n \"\n >\n <button\n [id]=\"datepicker.datepickerId + '-title'\"\n role=\"heading\"\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-calendar-title\"\n (click)=\"datepicker.toggleModeCalendar($event)\"\n [disabled]=\"datepicker.datepickerMode === datepicker.maxMode\"\n [ngClass]=\"{\n 'sky-btn-disabled': datepicker.datepickerMode === datepicker.maxMode\n }\"\n tabindex=\"-1\"\n >\n <strong>{{ title }}</strong>\n </button>\n </th>\n <th class=\"sky-datepicker-header-right\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-btn-sm sky-datepicker-btn-next\"\n (click)=\"datepicker.moveCalendar($event, 1)\"\n tabindex=\"-1\"\n >\n <sky-icon\n class=\"sky-datepicker-chevron-default\"\n icon=\"chevron-right\"\n ></sky-icon>\n <sky-icon\n class=\"sky-datepicker-chevron-modern\"\n icon=\"chevron-right\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of rows\">\n <td *ngFor=\"let date of row\" class=\"sky-datepicker-row\" role=\"gridcell\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-datepicker-btn-date\"\n [ngClass]=\"{\n 'sky-datepicker-btn-selected': date.selected,\n 'sky-btn-disabled': date.disabled,\n 'sky-btn-active': datepicker.isActive(date)\n }\"\n [disabled]=\"date.disabled\"\n (click)=\"datepicker.selectCalendar($event, date.date)\"\n tabindex=\"-1\"\n >\n <span [ngClass]=\"{ 'sky-datepicker-current': date.current }\">{{\n date.label\n }}</span>\n </button>\n </td>\n </tr>\n </tbody>\n</table>\n", styles: [":host-context(.sky-theme-modern) :host:focus{outline:none}.sky-theme-modern :host:focus{outline:none}\n"] }]
1797
+ }], ctorParameters: function () { return [{ type: SkyDatepickerCalendarInnerComponent }]; } });
1798
+
1799
+ /**
1800
+ * @internal
1801
+ */
1802
+ class SkyDatepickerCalendarComponent {
1803
+ constructor(adapter, config, elementRef) {
1804
+ this.adapter = adapter;
1805
+ this.config = config;
1806
+ this.elementRef = elementRef;
1807
+ this.calendarDateRangeChange = new EventEmitter();
1808
+ this.calendarModeChange = new EventEmitter();
1809
+ this.selectedDateChange = new EventEmitter(undefined);
1810
+ this._now = new Date();
1811
+ this.formatter = new SkyDateFormatter();
1812
+ this.configureOptions();
1813
+ }
1814
+ /** starting day of the week from 0-6 (0=Sunday, ..., 6=Saturday) */
1815
+ set startingDay(start) {
1816
+ this._startingDay = start;
1817
+ }
1818
+ get startingDay() {
1819
+ return this._startingDay || 0;
1820
+ }
1821
+ /**
1822
+ * @internal
1823
+ * Indicates if the calendar element's visiblity property is 'visible'.
1824
+ */
1825
+ get isVisible() {
1826
+ return this.adapter.elementIsVisible();
1827
+ }
1828
+ ngAfterViewInit() {
1829
+ this.adapter.init(this.elementRef);
1830
+ }
1831
+ configureOptions() {
1832
+ Object.assign(this, this.config);
1833
+ }
1834
+ onCalendarDateRangeChange(event) {
1835
+ this.calendarDateRangeChange.next(event);
1836
+ }
1837
+ onCalendarModeChange(event) {
1838
+ this.calendarModeChange.emit(event);
1839
+ }
1840
+ onSelectedDateChange(event) {
1841
+ this.selectedDateChange.emit(event);
1842
+ }
1843
+ writeValue(value) {
1844
+ if (value !== undefined &&
1845
+ this.formatter.dateIsValid(value) &&
1846
+ this.selectedDate !== undefined &&
1847
+ this._datepicker.compareHandlerDay(value, this.selectedDate) === 0) {
1848
+ return;
1849
+ }
1850
+ if (this.formatter.dateIsValid(value)) {
1851
+ this.selectedDate = value;
1852
+ this._datepicker.select(value, false);
1853
+ }
1854
+ else {
1855
+ this.selectedDate = new Date();
1856
+ this._datepicker.select(new Date(), false);
1857
+ }
1858
+ }
1859
+ }
1860
+ SkyDatepickerCalendarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerCalendarComponent, deps: [{ token: SkyDatepickerAdapterService }, { token: SkyDatepickerConfigService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
1861
+ SkyDatepickerCalendarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: SkyDatepickerCalendarComponent, selector: "sky-datepicker-calendar", inputs: { customDates: "customDates", isDaypickerWaiting: "isDaypickerWaiting", minDate: "minDate", maxDate: "maxDate", selectedDate: "selectedDate", startingDay: "startingDay" }, outputs: { calendarDateRangeChange: "calendarDateRangeChange", calendarModeChange: "calendarModeChange", selectedDateChange: "selectedDateChange" }, providers: [SkyDatepickerAdapterService], viewQueries: [{ propertyName: "_datepicker", first: true, predicate: SkyDatepickerCalendarInnerComponent, descendants: true, read: SkyDatepickerCalendarInnerComponent, static: true }], ngImport: i0, template: "<div class=\"sky-datepicker-calendar\">\n <sky-datepicker-inner\n [customDates]=\"customDates\"\n [maxDate]=\"maxDate\"\n [minDate]=\"minDate\"\n [selectedDate]=\"selectedDate\"\n [startingDay]=\"startingDay\"\n (calendarModeChange)=\"onCalendarModeChange($event)\"\n (selectedDateChange)=\"onSelectedDateChange($event)\"\n >\n <sky-daypicker\n tabindex=\"0\"\n [customDates]=\"customDates\"\n [isWaiting]=\"isDaypickerWaiting\"\n (calendarDateRangeChange)=\"onCalendarDateRangeChange($event)\"\n ></sky-daypicker>\n <sky-monthpicker tabindex=\"0\"></sky-monthpicker>\n <sky-yearpicker tabindex=\"0\"></sky-yearpicker>\n </sky-datepicker-inner>\n</div>\n", styles: [".sky-datepicker-calendar{display:block}\n"], components: [{ type: SkyDatepickerCalendarInnerComponent, selector: "sky-datepicker-inner", inputs: ["customDates", "startingDay", "minDate", "maxDate", "selectedDate"], outputs: ["selectedDateChange", "calendarModeChange"] }, { type: SkyDayPickerComponent, selector: "sky-daypicker", inputs: ["customDates", "isWaiting"], outputs: ["calendarDateRangeChange"] }, { type: SkyMonthPickerComponent, selector: "sky-monthpicker" }, { type: SkyYearPickerComponent, selector: "sky-yearpicker" }] });
1862
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerCalendarComponent, decorators: [{
1863
+ type: Component,
1864
+ args: [{ selector: 'sky-datepicker-calendar', providers: [SkyDatepickerAdapterService], template: "<div class=\"sky-datepicker-calendar\">\n <sky-datepicker-inner\n [customDates]=\"customDates\"\n [maxDate]=\"maxDate\"\n [minDate]=\"minDate\"\n [selectedDate]=\"selectedDate\"\n [startingDay]=\"startingDay\"\n (calendarModeChange)=\"onCalendarModeChange($event)\"\n (selectedDateChange)=\"onSelectedDateChange($event)\"\n >\n <sky-daypicker\n tabindex=\"0\"\n [customDates]=\"customDates\"\n [isWaiting]=\"isDaypickerWaiting\"\n (calendarDateRangeChange)=\"onCalendarDateRangeChange($event)\"\n ></sky-daypicker>\n <sky-monthpicker tabindex=\"0\"></sky-monthpicker>\n <sky-yearpicker tabindex=\"0\"></sky-yearpicker>\n </sky-datepicker-inner>\n</div>\n", styles: [".sky-datepicker-calendar{display:block}\n"] }]
1865
+ }], ctorParameters: function () { return [{ type: SkyDatepickerAdapterService }, { type: SkyDatepickerConfigService }, { type: i0.ElementRef }]; }, propDecorators: { customDates: [{
1866
+ type: Input
1867
+ }], isDaypickerWaiting: [{
1868
+ type: Input
1869
+ }], minDate: [{
1870
+ type: Input
1871
+ }], maxDate: [{
1872
+ type: Input
1873
+ }], selectedDate: [{
1874
+ type: Input
1875
+ }], startingDay: [{
1876
+ type: Input
1877
+ }], calendarDateRangeChange: [{
1878
+ type: Output
1879
+ }], calendarModeChange: [{
1880
+ type: Output
1881
+ }], selectedDateChange: [{
1882
+ type: Output
1883
+ }], _datepicker: [{
1884
+ type: ViewChild,
1885
+ args: [SkyDatepickerCalendarInnerComponent, {
1886
+ read: SkyDatepickerCalendarInnerComponent,
1887
+ static: true,
1888
+ }]
1889
+ }] } });
1890
+
1891
+ let nextId$1 = 0;
1892
+ /**
1893
+ * Creates the datepicker button and calendar.
1894
+ * You must wrap this component around an input with the `skyDatepickerInput` directive.
1895
+ */
1896
+ class SkyDatepickerComponent {
1897
+ constructor(affixService, changeDetector, coreAdapter, overlayService, inputBoxHostService, themeSvc) {
1898
+ this.affixService = affixService;
1899
+ this.changeDetector = changeDetector;
1900
+ this.coreAdapter = coreAdapter;
1901
+ this.overlayService = overlayService;
1902
+ this.inputBoxHostService = inputBoxHostService;
1903
+ /**
1904
+ * Adds a class to the datepicker.
1905
+ * @default ""
1906
+ */
1907
+ this.pickerClass = '';
1908
+ /**
1909
+ * Fires when the range of displayed dates in the calendar changes. Provides the
1910
+ * current range of displayed dates and a mutable `customDate` property consumers can use
1911
+ * to modify individual dates on the calendar.
1912
+ */
1913
+ this.calendarDateRangeChange = new EventEmitter();
1914
+ this.dateChange = new EventEmitter();
1915
+ this.isDaypickerWaiting = false;
1916
+ this.isOpen = false;
1917
+ this.isVisible = false;
1918
+ this.ngUnsubscribe = new Subject();
1919
+ this._disabled = false;
1920
+ const uniqueId = nextId$1++;
1921
+ this.calendarId = `sky-datepicker-calendar-${uniqueId}`;
1922
+ this.triggerButtonId = `sky-datepicker-button-${uniqueId}`;
1923
+ // Update icons when theme changes.
1924
+ themeSvc === null || themeSvc === void 0 ? void 0 : themeSvc.settingsChange.pipe(takeUntil(this.ngUnsubscribe)).subscribe(() => {
1925
+ this.changeDetector.markForCheck();
1926
+ });
1927
+ }
1928
+ /**
1929
+ * @internal
1930
+ * Indicates if the calendar button element or any of its children have focus.
1931
+ * @deprecated This property will be removed in the next major version release.
1932
+ */
1933
+ get buttonIsFocused() {
1934
+ /* sanity check */
1935
+ /* istanbul ignore if */
1936
+ if (!this.triggerButtonRef) {
1937
+ return false;
1938
+ }
1939
+ const activeEl = document.activeElement;
1940
+ return this.triggerButtonRef.nativeElement === activeEl;
1941
+ }
1942
+ /**
1943
+ * @internal
1944
+ * Indicates if the calendar element or any of its children have focus.
1945
+ * @deprecated This property will be removed in the next major version release.
1946
+ */
1947
+ get calendarIsFocused() {
1948
+ if (!this.calendarRef) {
1949
+ return false;
1950
+ }
1951
+ const focusedEl = document.activeElement;
1952
+ return this.calendarRef.nativeElement.contains(focusedEl);
1953
+ }
1954
+ /**
1955
+ * @internal
1956
+ * Indicates if the calendar element's visiblity property is 'visible'.
1957
+ * @deprecated This property will be removed in the next major version release.
1958
+ */
1959
+ get calendarIsVisible() {
1960
+ return this.calendar ? this.calendar.isVisible : false;
1961
+ }
1962
+ get disabled() {
1963
+ return this._disabled;
1964
+ }
1965
+ set disabled(value) {
1966
+ this._disabled = value;
1967
+ this.changeDetector.markForCheck();
1968
+ }
1969
+ set selectedDate(value) {
1970
+ this._selectedDate = value;
1971
+ if (this.calendar) {
1972
+ this.calendar.writeValue(this._selectedDate);
1973
+ }
1974
+ }
1975
+ set calendarRef(value) {
1976
+ if (value) {
1977
+ this._calendarRef = value;
1978
+ // Wait for the calendar component to render before gauging dimensions.
1979
+ setTimeout(() => {
1980
+ this.calendar.writeValue(this._selectedDate);
1981
+ this.destroyAffixer();
1982
+ this.createAffixer();
1983
+ setTimeout(() => {
1984
+ this.coreAdapter.getFocusableChildrenAndApplyFocus(this.calendarRef, '.sky-datepicker-calendar-inner', false);
1985
+ this.isVisible = true;
1986
+ this.changeDetector.markForCheck();
1987
+ });
1988
+ });
1989
+ }
1990
+ }
1991
+ get calendarRef() {
1992
+ return this._calendarRef;
1993
+ }
1994
+ ngOnInit() {
1995
+ if (this.inputBoxHostService) {
1996
+ this.inputBoxHostService.populate({
1997
+ inputTemplate: this.inputTemplateRef,
1998
+ buttonsTemplate: this.triggerButtonTemplateRef,
1999
+ });
2000
+ }
2001
+ }
2002
+ ngOnDestroy() {
2003
+ this.dateChange.complete();
2004
+ this.ngUnsubscribe.next();
2005
+ this.ngUnsubscribe.complete();
2006
+ this.removePickerEventListeners();
2007
+ this.destroyAffixer();
2008
+ this.destroyOverlay();
2009
+ }
2010
+ onCalendarModeChange() {
2011
+ // Let the calendar populate in the DOM before recalculating placement.
2012
+ setTimeout(() => {
2013
+ this.affixer.reaffix();
2014
+ });
2015
+ }
2016
+ onSelectedDateChange(value) {
2017
+ this.dateChange.emit(value);
2018
+ this.closePicker();
2019
+ }
2020
+ onTriggerButtonClick() {
2021
+ if (this.isOpen) {
2022
+ this.closePicker();
2023
+ }
2024
+ else {
2025
+ this.openPicker();
2026
+ }
2027
+ }
2028
+ onCalendarDateRangeChange(event) {
2029
+ /* istanbul ignore else */
2030
+ if (event) {
2031
+ this.cancelCustomDatesSubscription();
2032
+ const args = {
2033
+ startDate: event.startDate,
2034
+ endDate: event.endDate,
2035
+ customDates: undefined,
2036
+ };
2037
+ this.calendarDateRangeChange.emit(args);
2038
+ // If consumer has added an observable to the args, watch for incoming custom dates.
2039
+ /* istanbul ignore else */
2040
+ if (args.customDates) {
2041
+ this.isDaypickerWaiting = true;
2042
+ // Avoid an ExpressionChangedAfterItHasBeenCheckedError.
2043
+ this.changeDetector.detectChanges();
2044
+ this.customDatesSubscription = args.customDates
2045
+ .pipe(debounceTime(250))
2046
+ .subscribe((result) => {
2047
+ this.customDates = result;
2048
+ this.isDaypickerWaiting = false;
2049
+ // Trigger change detection in child components to show changes in the calendar.
2050
+ this.changeDetector.markForCheck();
2051
+ });
2052
+ }
2053
+ else {
2054
+ // If consumer returns an undefined value after custom dates have
2055
+ // already ben established, remove custom dates.
2056
+ if (this.customDates) {
2057
+ this.customDates = undefined;
2058
+ // Avoid an ExpressionChangedAfterItHasBeenCheckedError.
2059
+ this.changeDetector.detectChanges();
2060
+ }
2061
+ }
2062
+ }
2063
+ }
2064
+ closePicker() {
2065
+ this.destroyAffixer();
2066
+ this.destroyOverlay();
2067
+ this.removePickerEventListeners();
2068
+ this.triggerButtonRef.nativeElement.focus();
2069
+ this.isOpen = false;
2070
+ }
2071
+ openPicker() {
2072
+ this.isVisible = false;
2073
+ this.changeDetector.markForCheck();
2074
+ this.removePickerEventListeners();
2075
+ this.calendarUnsubscribe = new Subject();
2076
+ this.destroyOverlay();
2077
+ this.createOverlay();
2078
+ this.isOpen = true;
2079
+ this.changeDetector.markForCheck();
2080
+ }
2081
+ createAffixer() {
2082
+ const affixer = this.affixService.createAffixer(this.calendarRef);
2083
+ // Hide calendar when trigger button is scrolled off screen.
2084
+ affixer.placementChange
2085
+ .pipe(takeUntil(this.calendarUnsubscribe))
2086
+ .subscribe((change) => {
2087
+ this.isVisible = change.placement !== null;
2088
+ this.changeDetector.markForCheck();
2089
+ });
2090
+ affixer.affixTo(this.triggerButtonRef.nativeElement, {
2091
+ autoFitContext: SkyAffixAutoFitContext.Viewport,
2092
+ enableAutoFit: true,
2093
+ horizontalAlignment: 'right',
2094
+ isSticky: true,
2095
+ placement: 'below',
2096
+ });
2097
+ this.affixer = affixer;
2098
+ }
2099
+ destroyAffixer() {
2100
+ /*istanbul ignore else*/
2101
+ if (this.affixer) {
2102
+ this.affixer.destroy();
2103
+ this.affixer = undefined;
2104
+ }
2105
+ }
2106
+ createOverlay() {
2107
+ const overlay = this.overlayService.create({
2108
+ wrapperClass: this.pickerClass,
2109
+ enableClose: false,
2110
+ enablePointerEvents: false,
2111
+ });
2112
+ overlay.backdropClick
2113
+ .pipe(takeUntil(this.calendarUnsubscribe))
2114
+ .subscribe(() => {
2115
+ /* istanbul ignore else */
2116
+ if (this.isOpen) {
2117
+ this.closePicker();
2118
+ }
2119
+ });
2120
+ this.addKeydownListner();
2121
+ overlay.attachTemplate(this.calendarTemplateRef);
2122
+ this.overlay = overlay;
2123
+ }
2124
+ destroyOverlay() {
2125
+ /*istanbul ignore else*/
2126
+ if (this.overlay) {
2127
+ this.overlayService.close(this.overlay);
2128
+ this.overlay = undefined;
2129
+ }
2130
+ }
2131
+ addKeydownListner() {
2132
+ this.overlayKeydownListner = fromEvent(window.document, 'keydown')
2133
+ .pipe(takeUntil(this.ngUnsubscribe))
2134
+ .subscribe((event) => {
2135
+ var _a;
2136
+ const key = (_a = event.key) === null || _a === void 0 ? void 0 : _a.toLowerCase();
2137
+ if (key === 'escape' && this.isOpen) {
2138
+ this.closePicker();
2139
+ }
2140
+ });
2141
+ }
2142
+ removePickerEventListeners() {
2143
+ var _a;
2144
+ /* istanbul ignore else */
2145
+ if (this.calendarUnsubscribe) {
2146
+ this.calendarUnsubscribe.next();
2147
+ this.calendarUnsubscribe.complete();
2148
+ this.calendarUnsubscribe = undefined;
2149
+ }
2150
+ (_a = this.overlayKeydownListner) === null || _a === void 0 ? void 0 : _a.unsubscribe();
2151
+ }
2152
+ cancelCustomDatesSubscription() {
2153
+ if (this.customDatesSubscription) {
2154
+ this.customDatesSubscription.unsubscribe();
2155
+ this.customDatesSubscription = undefined;
2156
+ }
2157
+ }
2158
+ }
2159
+ SkyDatepickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerComponent, deps: [{ token: i1.SkyAffixService }, { token: i0.ChangeDetectorRef }, { token: i1.SkyCoreAdapterService }, { token: i1.SkyOverlayService }, { token: i2$1.SkyInputBoxHostService, optional: true }, { token: i3$2.SkyThemeService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
2160
+ SkyDatepickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: SkyDatepickerComponent, selector: "sky-datepicker", inputs: { pickerClass: "pickerClass" }, outputs: { calendarDateRangeChange: "calendarDateRangeChange" }, viewQueries: [{ propertyName: "calendar", first: true, predicate: SkyDatepickerCalendarComponent, descendants: true }, { propertyName: "calendarRef", first: true, predicate: ["calendarRef"], descendants: true, read: ElementRef }, { propertyName: "calendarTemplateRef", first: true, predicate: ["calendarTemplateRef"], descendants: true, read: TemplateRef }, { propertyName: "triggerButtonRef", first: true, predicate: ["triggerButtonRef"], descendants: true, read: ElementRef }, { propertyName: "inputTemplateRef", first: true, predicate: ["inputTemplateRef"], descendants: true, read: TemplateRef, static: true }, { propertyName: "triggerButtonTemplateRef", first: true, predicate: ["triggerButtonTemplateRef"], descendants: true, read: TemplateRef, static: true }], ngImport: i0, template: "<div class=\"sky-datepicker\">\n <ng-container *ngIf=\"!inputBoxHostService\">\n <div class=\"sky-input-group\">\n <ng-container *ngTemplateOutlet=\"inputTemplateRef\"></ng-container>\n <ng-container *ngTemplateOutlet=\"triggerButtonTemplateRef\"></ng-container>\n </div>\n </ng-container>\n</div>\n\n<ng-template #inputTemplateRef>\n <ng-content></ng-content>\n</ng-template>\n\n<ng-template #triggerButtonTemplateRef>\n <div class=\"sky-input-group-btn\">\n <button\n aria-haspopup=\"dialog\"\n class=\"sky-btn sky-btn-default sky-input-group-datepicker-btn\"\n type=\"button\"\n [attr.aria-controls]=\"isOpen ? calendarId : null\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-label]=\"\n 'skyux_datepicker_trigger_button_label' | skyLibResources\n \"\n [attr.id]=\"triggerButtonId\"\n [attr.title]=\"'skyux_datepicker_trigger_button_label' | skyLibResources\"\n [disabled]=\"disabled\"\n (click)=\"onTriggerButtonClick()\"\n #triggerButtonRef\n >\n <sky-icon *skyThemeIf=\"'default'\" icon=\"calendar\" size=\"lg\"></sky-icon>\n <sky-icon\n *skyThemeIf=\"'modern'\"\n icon=\"calendar\"\n size=\"lg\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </div>\n</ng-template>\n\n<ng-template #calendarTemplateRef>\n <div\n class=\"sky-datepicker-calendar-container sky-shadow sky-elevation-4\"\n role=\"dialog\"\n [attr.aria-labelledby]=\"triggerButtonId\"\n [attr.id]=\"calendarId\"\n [class.sky-datepicker-hidden]=\"!isVisible\"\n #calendarRef\n >\n <sky-datepicker-calendar\n [customDates]=\"customDates\"\n [isDaypickerWaiting]=\"isDaypickerWaiting\"\n [maxDate]=\"maxDate\"\n [minDate]=\"minDate\"\n [startingDay]=\"startingDay\"\n (calendarDateRangeChange)=\"onCalendarDateRangeChange($event)\"\n (calendarModeChange)=\"onCalendarModeChange()\"\n (selectedDateChange)=\"onSelectedDateChange($event)\"\n >\n </sky-datepicker-calendar>\n </div>\n</ng-template>\n", styles: [".sky-datepicker-calendar-container{position:fixed;border-radius:5px}.sky-datepicker-hidden{visibility:hidden}\n"], components: [{ type: i2.λ4, selector: "sky-icon", inputs: ["icon", "iconType", "size", "fixedWidth", "variant"] }, { type: SkyDatepickerCalendarComponent, selector: "sky-datepicker-calendar", inputs: ["customDates", "isDaypickerWaiting", "minDate", "maxDate", "selectedDate", "startingDay"], outputs: ["calendarDateRangeChange", "calendarModeChange", "selectedDateChange"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3$2.λ3, selector: "[skyThemeIf]", inputs: ["skyThemeIf"] }], pipes: { "skyLibResources": i3.SkyLibResourcesPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
2161
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerComponent, decorators: [{
2162
+ type: Component,
2163
+ args: [{ selector: 'sky-datepicker', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sky-datepicker\">\n <ng-container *ngIf=\"!inputBoxHostService\">\n <div class=\"sky-input-group\">\n <ng-container *ngTemplateOutlet=\"inputTemplateRef\"></ng-container>\n <ng-container *ngTemplateOutlet=\"triggerButtonTemplateRef\"></ng-container>\n </div>\n </ng-container>\n</div>\n\n<ng-template #inputTemplateRef>\n <ng-content></ng-content>\n</ng-template>\n\n<ng-template #triggerButtonTemplateRef>\n <div class=\"sky-input-group-btn\">\n <button\n aria-haspopup=\"dialog\"\n class=\"sky-btn sky-btn-default sky-input-group-datepicker-btn\"\n type=\"button\"\n [attr.aria-controls]=\"isOpen ? calendarId : null\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-label]=\"\n 'skyux_datepicker_trigger_button_label' | skyLibResources\n \"\n [attr.id]=\"triggerButtonId\"\n [attr.title]=\"'skyux_datepicker_trigger_button_label' | skyLibResources\"\n [disabled]=\"disabled\"\n (click)=\"onTriggerButtonClick()\"\n #triggerButtonRef\n >\n <sky-icon *skyThemeIf=\"'default'\" icon=\"calendar\" size=\"lg\"></sky-icon>\n <sky-icon\n *skyThemeIf=\"'modern'\"\n icon=\"calendar\"\n size=\"lg\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </div>\n</ng-template>\n\n<ng-template #calendarTemplateRef>\n <div\n class=\"sky-datepicker-calendar-container sky-shadow sky-elevation-4\"\n role=\"dialog\"\n [attr.aria-labelledby]=\"triggerButtonId\"\n [attr.id]=\"calendarId\"\n [class.sky-datepicker-hidden]=\"!isVisible\"\n #calendarRef\n >\n <sky-datepicker-calendar\n [customDates]=\"customDates\"\n [isDaypickerWaiting]=\"isDaypickerWaiting\"\n [maxDate]=\"maxDate\"\n [minDate]=\"minDate\"\n [startingDay]=\"startingDay\"\n (calendarDateRangeChange)=\"onCalendarDateRangeChange($event)\"\n (calendarModeChange)=\"onCalendarModeChange()\"\n (selectedDateChange)=\"onSelectedDateChange($event)\"\n >\n </sky-datepicker-calendar>\n </div>\n</ng-template>\n", styles: [".sky-datepicker-calendar-container{position:fixed;border-radius:5px}.sky-datepicker-hidden{visibility:hidden}\n"] }]
2164
+ }], ctorParameters: function () {
2165
+ return [{ type: i1.SkyAffixService }, { type: i0.ChangeDetectorRef }, { type: i1.SkyCoreAdapterService }, { type: i1.SkyOverlayService }, { type: i2$1.SkyInputBoxHostService, decorators: [{
2166
+ type: Optional
2167
+ }] }, { type: i3$2.SkyThemeService, decorators: [{
2168
+ type: Optional
2169
+ }] }];
2170
+ }, propDecorators: { pickerClass: [{
2171
+ type: Input
2172
+ }], calendarDateRangeChange: [{
2173
+ type: Output
2174
+ }], calendar: [{
2175
+ type: ViewChild,
2176
+ args: [SkyDatepickerCalendarComponent]
2177
+ }], calendarRef: [{
2178
+ type: ViewChild,
2179
+ args: ['calendarRef', {
2180
+ read: ElementRef,
2181
+ }]
2182
+ }], calendarTemplateRef: [{
2183
+ type: ViewChild,
2184
+ args: ['calendarTemplateRef', {
2185
+ read: TemplateRef,
2186
+ }]
2187
+ }], triggerButtonRef: [{
2188
+ type: ViewChild,
2189
+ args: ['triggerButtonRef', {
2190
+ read: ElementRef,
2191
+ }]
2192
+ }], inputTemplateRef: [{
2193
+ type: ViewChild,
2194
+ args: ['inputTemplateRef', {
2195
+ read: TemplateRef,
2196
+ static: true,
2197
+ }]
2198
+ }], triggerButtonTemplateRef: [{
2199
+ type: ViewChild,
2200
+ args: ['triggerButtonTemplateRef', {
2201
+ read: TemplateRef,
2202
+ static: true,
2203
+ }]
2204
+ }] } });
2205
+
2206
+ // tslint:disable:no-forward-ref no-use-before-declare
2207
+ const SKY_FUZZY_DATEPICKER_VALUE_ACCESSOR = {
2208
+ provide: NG_VALUE_ACCESSOR,
2209
+ useExisting: forwardRef(() => SkyFuzzyDatepickerInputDirective),
2210
+ multi: true,
2211
+ };
2212
+ const SKY_FUZZY_DATEPICKER_VALIDATOR = {
2213
+ provide: NG_VALIDATORS,
2214
+ useExisting: forwardRef(() => SkyFuzzyDatepickerInputDirective),
2215
+ multi: true,
2216
+ };
2217
+ // tslint:enable
2218
+ class SkyFuzzyDatepickerInputDirective {
2219
+ constructor(changeDetector, configService, elementRef, fuzzyDateService, localeProvider, renderer, resourcesService, datepickerComponent) {
2220
+ this.changeDetector = changeDetector;
2221
+ this.configService = configService;
2222
+ this.elementRef = elementRef;
2223
+ this.fuzzyDateService = fuzzyDateService;
2224
+ this.localeProvider = localeProvider;
2225
+ this.renderer = renderer;
2226
+ this.resourcesService = resourcesService;
2227
+ this.datepickerComponent = datepickerComponent;
2228
+ /**
2229
+ * Indicates whether to disable date validation on the fuzzy datepicker input.
2230
+ * @default false
2231
+ */
2232
+ this.skyDatepickerNoValidate = false;
2233
+ this.dateFormatter = new SkyDateFormatter();
2234
+ this.ngUnsubscribe = new Subject();
2235
+ this._futureDisabled = false;
2236
+ this._disabled = false;
2237
+ this._yearRequired = false;
2238
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
2239
+ this.onChange = (_) => { };
2240
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
2241
+ this.onTouched = () => { };
2242
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
2243
+ this.onValidatorChange = () => { };
2244
+ this.localeProvider
2245
+ .getLocaleInfo()
2246
+ .pipe(takeUntil(this.ngUnsubscribe))
2247
+ .subscribe((localeInfo) => {
2248
+ this.locale = localeInfo.locale;
2249
+ SkyDateFormatter.setLocale(this.locale);
2250
+ this.preferredShortDateFormat =
2251
+ SkyDateFormatter.getPreferredShortDateFormat();
2252
+ });
2253
+ }
2254
+ /**
2255
+ * Specifies the date format for the input. Place this attribute on the `input` element
2256
+ * to override the default in `SkyDatepickerConfigService`.
2257
+ * @default "MM/DD/YYYY"
2258
+ */
2259
+ set dateFormat(value) {
2260
+ this._dateFormat = value;
2261
+ if (this.value) {
2262
+ const formattedDate = this.fuzzyDateService.format(this.value, this.dateFormat, this.locale);
2263
+ this.setInputElementValue(formattedDate);
2264
+ this.changeDetector.markForCheck();
2265
+ }
2266
+ }
2267
+ get dateFormat() {
2268
+ return (this._dateFormat ||
2269
+ this.configService.dateFormat ||
2270
+ this.preferredShortDateFormat);
2271
+ }
2272
+ /**
2273
+ * Indicates whether to disable the datepicker.
2274
+ * @default false
2275
+ */
2276
+ set disabled(value) {
2277
+ this._disabled = value;
2278
+ this.datepickerComponent.disabled = value;
2279
+ this.renderer.setProperty(this.elementRef.nativeElement, 'disabled', value);
2280
+ }
2281
+ get disabled() {
2282
+ return this._disabled;
2283
+ }
2284
+ /**
2285
+ * Indicates whether to prevent users from specifying dates that are in the future.
2286
+ * Place this attribute on the `input` element.
2287
+ * @default false
2288
+ */
2289
+ set futureDisabled(value) {
2290
+ this._futureDisabled = value;
2291
+ this.onValidatorChange();
2292
+ }
2293
+ get futureDisabled() {
2294
+ return this._futureDisabled;
2295
+ }
2296
+ /**
2297
+ * Specifies the latest fuzzy date allowed. Place this attribute on the `input` element
2298
+ * to prevent fuzzy dates after a specified date. This property accepts
2299
+ * a `SkyFuzzyDate` value that includes numeric month, day, and year values.
2300
+ * For example: `{ month: 1, day: 1, year: 2027 }`.
2301
+ */
2302
+ set maxDate(value) {
2303
+ this._maxDate = value;
2304
+ this.datepickerComponent.maxDate = this.getMaxDate();
2305
+ this.onValidatorChange();
2306
+ }
2307
+ get maxDate() {
2308
+ return this._maxDate;
2309
+ }
2310
+ /**
2311
+ * Specifies the earliest fuzzy date allowed. Place this attribute on the `input` element
2312
+ * to prevent fuzzy dates before a specified date. This property accepts a `SkyFuzzyDate` value
2313
+ * that includes numeric month, day, and year values.
2314
+ * For example: `{ month: 1, day: 1, year: 2007 }`.
2315
+ */
2316
+ set minDate(value) {
2317
+ this._minDate = value;
2318
+ this.datepickerComponent.minDate = this.getMinDate();
2319
+ this.onValidatorChange();
2320
+ }
2321
+ get minDate() {
2322
+ return this._minDate;
2323
+ }
2324
+ /**
2325
+ * Creates the fuzzy datepicker input and calendar to let users specify dates that are
2326
+ * not complete. For example, if users know the year but not the month or day, they can
2327
+ * enter just the year. Place this directive on an `input` element, and wrap the `input`
2328
+ * in a `sky-datepicker` component. The value that users select is driven
2329
+ * through the `ngModel` attribute specified on the `input` element.
2330
+ * @required
2331
+ */
2332
+ set skyFuzzyDatepickerInput(value) {
2333
+ // TODO: Remove this property in a future version of SKY UX.
2334
+ }
2335
+ /**
2336
+ * Specifies the starting day of the week in the calendar, where `0` sets the starting day
2337
+ * to Sunday. Place this attribute on the `input` element to override the default
2338
+ * in `SkyDatepickerConfigService`.
2339
+ * @default 0
2340
+ */
2341
+ set startingDay(value) {
2342
+ this._startingDay = value;
2343
+ this.datepickerComponent.startingDay = this.startingDay;
2344
+ this.onValidatorChange();
2345
+ }
2346
+ get startingDay() {
2347
+ return this._startingDay || this.configService.startingDay;
2348
+ }
2349
+ /**
2350
+ * Indicates whether to require the year in fuzzy dates.
2351
+ * @default false
2352
+ */
2353
+ set yearRequired(value) {
2354
+ this._yearRequired = value;
2355
+ this.onValidatorChange();
2356
+ }
2357
+ get yearRequired() {
2358
+ return this._yearRequired;
2359
+ }
2360
+ get value() {
2361
+ return this._value;
2362
+ }
2363
+ set value(value) {
2364
+ this.updateValue(value);
2365
+ }
2366
+ ngOnInit() {
2367
+ if (this.yearRequired) {
2368
+ if (this.dateFormat.toLowerCase().indexOf('y') === -1) {
2369
+ throw new Error('You have configured conflicting settings. Year is required and dateFormat does not include year.');
2370
+ }
2371
+ }
2372
+ if (!this.datepickerComponent) {
2373
+ throw new Error('You must wrap the `skyFuzzyDatepickerInput` directive within a ' +
2374
+ '`<sky-datepicker>` component!');
2375
+ }
2376
+ const element = this.elementRef.nativeElement;
2377
+ this.renderer.addClass(element, 'sky-form-control');
2378
+ const hasAriaLabel = element.getAttribute('aria-label');
2379
+ /* istanbul ignore else */
2380
+ if (!hasAriaLabel) {
2381
+ this.resourcesService
2382
+ .getString('skyux_date_field_default_label')
2383
+ .pipe(takeUntil(this.ngUnsubscribe))
2384
+ .subscribe((value) => {
2385
+ this.renderer.setAttribute(element, 'aria-label', value);
2386
+ });
2387
+ }
2388
+ }
2389
+ ngAfterContentInit() {
2390
+ this.datepickerComponent.dateChange
2391
+ .pipe(distinctUntilChanged(), takeUntil(this.ngUnsubscribe))
2392
+ .subscribe((value) => {
2393
+ this.value = value;
2394
+ this.onTouched();
2395
+ });
2396
+ }
2397
+ ngAfterViewInit() {
2398
+ // This is needed to address a bug in Angular 4.
2399
+ // When a control value is set intially, its value is not represented on the view.
2400
+ // See: https://github.com/angular/angular/issues/13792
2401
+ // Of note is the parent check which allows us to determine if the form is reactive.
2402
+ // Without this check there is a changed before checked error
2403
+ /* istanbul ignore else */
2404
+ if (this.control && this.control.parent) {
2405
+ setTimeout(() => {
2406
+ this.control.setValue(this.value, {
2407
+ emitEvent: false,
2408
+ });
2409
+ this.changeDetector.markForCheck();
2410
+ });
2411
+ }
2412
+ }
2413
+ ngOnDestroy() {
2414
+ this.ngUnsubscribe.next();
2415
+ this.ngUnsubscribe.complete();
2416
+ }
2417
+ onInputChange(event) {
2418
+ this.onValueChange(event.target.value);
2419
+ }
2420
+ onInputBlur() {
2421
+ this.onTouched();
2422
+ const formattedDate = this.fuzzyDateService.format(this.value, this.dateFormat, this.locale);
2423
+ if (this.control.valid) {
2424
+ this.setInputElementValue(formattedDate);
2425
+ }
2426
+ }
2427
+ onInputKeyup() {
2428
+ this.control.markAsDirty();
2429
+ }
2430
+ writeValue(value) {
2431
+ this.updateValue(value, false);
2432
+ }
2433
+ validate(control) {
2434
+ if (!this.control) {
2435
+ this.control = control;
2436
+ }
2437
+ if (this.skyDatepickerNoValidate) {
2438
+ return;
2439
+ }
2440
+ if (!this.control.value) {
2441
+ return;
2442
+ }
2443
+ const value = control.value;
2444
+ let fuzzyDate;
2445
+ let validationError;
2446
+ if (typeof value === 'string') {
2447
+ fuzzyDate = this.fuzzyDateService.getFuzzyDateFromString(value, this.dateFormat);
2448
+ }
2449
+ else {
2450
+ fuzzyDate = value;
2451
+ }
2452
+ if (!fuzzyDate) {
2453
+ validationError = {
2454
+ skyFuzzyDate: {
2455
+ invalid: value,
2456
+ },
2457
+ };
2458
+ }
2459
+ if (!validationError && !fuzzyDate.year && this.yearRequired) {
2460
+ validationError = {
2461
+ skyFuzzyDate: {
2462
+ yearRequired: value,
2463
+ },
2464
+ };
2465
+ }
2466
+ if (!validationError && fuzzyDate.year) {
2467
+ let fuzzyDateRange;
2468
+ if (this.maxDate) {
2469
+ fuzzyDateRange = this.fuzzyDateService.getFuzzyDateRange(fuzzyDate, this.maxDate);
2470
+ if (!fuzzyDateRange.valid) {
2471
+ validationError = {
2472
+ skyFuzzyDate: {
2473
+ maxDate: value,
2474
+ },
2475
+ };
2476
+ }
2477
+ }
2478
+ if (!validationError && this.minDate) {
2479
+ fuzzyDateRange = this.fuzzyDateService.getFuzzyDateRange(this.minDate, fuzzyDate);
2480
+ if (!fuzzyDateRange.valid) {
2481
+ validationError = {
2482
+ skyFuzzyDate: {
2483
+ minDate: value,
2484
+ },
2485
+ };
2486
+ }
2487
+ }
2488
+ if (!validationError && this.futureDisabled) {
2489
+ fuzzyDateRange = this.fuzzyDateService.getFuzzyDateRange(fuzzyDate, this.fuzzyDateService.getCurrentFuzzyDate());
2490
+ if (!fuzzyDateRange.valid) {
2491
+ validationError = {
2492
+ skyFuzzyDate: {
2493
+ futureDisabled: value,
2494
+ },
2495
+ };
2496
+ }
2497
+ }
2498
+ }
2499
+ if (validationError) {
2500
+ // Mark the invalid control as touched so that the input's invalid CSS styles appear.
2501
+ // (This is only required when the invalid value is set by the FormControl constructor.)
2502
+ this.control.markAsTouched();
2503
+ }
2504
+ return validationError;
2505
+ }
2506
+ registerOnChange(fn) {
2507
+ this.onChange = fn;
2508
+ }
2509
+ registerOnTouched(fn) {
2510
+ this.onTouched = fn;
2511
+ }
2512
+ registerOnValidatorChange(fn) {
2513
+ this.onValidatorChange = fn;
2514
+ }
2515
+ setDisabledState(disabled) {
2516
+ this.disabled = disabled;
2517
+ this.datepickerComponent.disabled = disabled;
2518
+ }
2519
+ /**
2520
+ * Detects changes to the underlying input element's value and updates the ngModel accordingly.
2521
+ * This is useful if you need to update the ngModel value before the input element loses focus.
2522
+ */
2523
+ detectInputValueChange() {
2524
+ this.onValueChange(this.elementRef.nativeElement.value);
2525
+ }
2526
+ onValueChange(newValue) {
2527
+ this.value = newValue;
2528
+ }
2529
+ setInputElementValue(value) {
2530
+ this.renderer.setProperty(this.elementRef.nativeElement, 'value', value);
2531
+ }
2532
+ getMaxDate() {
2533
+ if (this.maxDate) {
2534
+ const maxDate = this.fuzzyDateService.getMomentFromFuzzyDate(this.maxDate);
2535
+ if (maxDate.isValid()) {
2536
+ return maxDate.toDate();
2537
+ }
2538
+ }
2539
+ else if (this.futureDisabled) {
2540
+ return new Date();
2541
+ }
2542
+ return this.configService.maxDate;
2543
+ }
2544
+ getMinDate() {
2545
+ if (this.minDate) {
2546
+ const minDate = this.fuzzyDateService.getMomentFromFuzzyDate(this.minDate);
2547
+ if (minDate.isValid()) {
2548
+ return minDate.toDate();
2549
+ }
2550
+ }
2551
+ return this.configService.minDate;
2552
+ }
2553
+ /* istanbul ignore next */
2554
+ fuzzyDatesEqual(dateA, dateB) {
2555
+ return (dateA &&
2556
+ dateB &&
2557
+ ((!dateA.day && !dateB.day) || dateA.day === dateB.day) &&
2558
+ ((!dateA.month && !dateB.month) || dateA.month === dateB.month) &&
2559
+ ((!dateA.year && !dateB.year) || dateA.year === dateB.year));
2560
+ }
2561
+ /**
2562
+ * Update the value of the form control and input element
2563
+ * @param emitEvent Denotes if we emit an event to the consumer's form control. We do not want to do this if the value is being updated via a `setValue` call or a `patchValue` call as this is already handled by Angular.
2564
+ * In these cases we do not want to fire `onChange` as it will cause extra `valueChange` and `statusChange` events and the status of the form should not be affected by these changes.
2565
+ */
2566
+ updateValue(value, emitEvent = true) {
2567
+ var _a;
2568
+ if (this._value === value) {
2569
+ return;
2570
+ }
2571
+ let fuzzyDate;
2572
+ let fuzzyMoment;
2573
+ let dateValue;
2574
+ let formattedDate;
2575
+ if (value instanceof Date) {
2576
+ dateValue = value;
2577
+ formattedDate = this.dateFormatter.format(value, this.dateFormat);
2578
+ fuzzyDate = this.fuzzyDateService.getFuzzyDateFromSelectedDate(value, this.dateFormat);
2579
+ }
2580
+ else if (typeof value === 'string') {
2581
+ fuzzyDate = this.fuzzyDateService.getFuzzyDateFromString(value, this.dateFormat);
2582
+ formattedDate = this.fuzzyDateService.format(fuzzyDate, this.dateFormat, this.locale);
2583
+ if (!formattedDate) {
2584
+ formattedDate = value;
2585
+ }
2586
+ fuzzyMoment = this.fuzzyDateService.getMomentFromFuzzyDate(fuzzyDate);
2587
+ if (fuzzyMoment) {
2588
+ dateValue = fuzzyMoment.toDate();
2589
+ }
2590
+ }
2591
+ else {
2592
+ fuzzyDate = value;
2593
+ formattedDate = this.fuzzyDateService.format(fuzzyDate, this.dateFormat, this.locale);
2594
+ fuzzyMoment = this.fuzzyDateService.getMomentFromFuzzyDate(fuzzyDate);
2595
+ if (fuzzyMoment) {
2596
+ dateValue = fuzzyMoment.toDate();
2597
+ }
2598
+ }
2599
+ const areFuzzyDatesEqual = this.fuzzyDatesEqual(this._value, fuzzyDate);
2600
+ const isNewValue = fuzzyDate !== this._value || !areFuzzyDatesEqual;
2601
+ this._value = fuzzyDate || value;
2602
+ if (isNewValue) {
2603
+ if (emitEvent) {
2604
+ this.onChange(this._value);
2605
+ }
2606
+ else {
2607
+ (_a = this.control) === null || _a === void 0 ? void 0 : _a.setValue(this._value, { emitEvent: false });
2608
+ }
2609
+ this.datepickerComponent.selectedDate = dateValue;
2610
+ }
2611
+ this.setInputElementValue(formattedDate || '');
2612
+ }
2613
+ }
2614
+ SkyFuzzyDatepickerInputDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyFuzzyDatepickerInputDirective, deps: [{ token: i0.ChangeDetectorRef }, { token: SkyDatepickerConfigService }, { token: i0.ElementRef }, { token: SkyFuzzyDateService }, { token: i3.SkyAppLocaleProvider }, { token: i0.Renderer2 }, { token: i3.SkyLibResourcesService }, { token: SkyDatepickerComponent, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
2615
+ SkyFuzzyDatepickerInputDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.2.7", type: SkyFuzzyDatepickerInputDirective, selector: "[skyFuzzyDatepickerInput]", inputs: { dateFormat: "dateFormat", disabled: "disabled", futureDisabled: "futureDisabled", maxDate: "maxDate", minDate: "minDate", skyDatepickerNoValidate: "skyDatepickerNoValidate", skyFuzzyDatepickerInput: "skyFuzzyDatepickerInput", startingDay: "startingDay", yearRequired: "yearRequired" }, host: { listeners: { "change": "onInputChange($event)", "blur": "onInputBlur()", "keyup": "onInputKeyup()" } }, providers: [
2616
+ SKY_FUZZY_DATEPICKER_VALUE_ACCESSOR,
2617
+ SKY_FUZZY_DATEPICKER_VALIDATOR,
2618
+ ], ngImport: i0 });
2619
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyFuzzyDatepickerInputDirective, decorators: [{
2620
+ type: Directive,
2621
+ args: [{
2622
+ selector: '[skyFuzzyDatepickerInput]',
2623
+ providers: [
2624
+ SKY_FUZZY_DATEPICKER_VALUE_ACCESSOR,
2625
+ SKY_FUZZY_DATEPICKER_VALIDATOR,
2626
+ ],
2627
+ }]
2628
+ }], ctorParameters: function () {
2629
+ return [{ type: i0.ChangeDetectorRef }, { type: SkyDatepickerConfigService }, { type: i0.ElementRef }, { type: SkyFuzzyDateService }, { type: i3.SkyAppLocaleProvider }, { type: i0.Renderer2 }, { type: i3.SkyLibResourcesService }, { type: SkyDatepickerComponent, decorators: [{
2630
+ type: Optional
2631
+ }] }];
2632
+ }, propDecorators: { dateFormat: [{
2633
+ type: Input
2634
+ }], disabled: [{
2635
+ type: Input
2636
+ }], futureDisabled: [{
2637
+ type: Input
2638
+ }], maxDate: [{
2639
+ type: Input
2640
+ }], minDate: [{
2641
+ type: Input
2642
+ }], skyDatepickerNoValidate: [{
2643
+ type: Input
2644
+ }], skyFuzzyDatepickerInput: [{
2645
+ type: Input
2646
+ }], startingDay: [{
2647
+ type: Input
2648
+ }], yearRequired: [{
2649
+ type: Input
2650
+ }], onInputChange: [{
2651
+ type: HostListener,
2652
+ args: ['change', ['$event']]
2653
+ }], onInputBlur: [{
2654
+ type: HostListener,
2655
+ args: ['blur']
2656
+ }], onInputKeyup: [{
2657
+ type: HostListener,
2658
+ args: ['keyup']
2659
+ }] } });
2660
+
2661
+ // tslint:disable:no-forward-ref no-use-before-declare
2662
+ const SKY_DATEPICKER_VALUE_ACCESSOR = {
2663
+ provide: NG_VALUE_ACCESSOR,
2664
+ useExisting: forwardRef(() => SkyDatepickerInputDirective),
2665
+ multi: true,
2666
+ };
2667
+ const SKY_DATEPICKER_VALIDATOR = {
2668
+ provide: NG_VALIDATORS,
2669
+ useExisting: forwardRef(() => SkyDatepickerInputDirective),
2670
+ multi: true,
2671
+ };
2672
+ // tslint:enable
2673
+ class SkyDatepickerInputDirective {
2674
+ constructor(adapter, changeDetector, configService, elementRef, localeProvider, renderer, resourcesService, datepickerComponent) {
2675
+ this.adapter = adapter;
2676
+ this.changeDetector = changeDetector;
2677
+ this.configService = configService;
2678
+ this.elementRef = elementRef;
2679
+ this.localeProvider = localeProvider;
2680
+ this.renderer = renderer;
2681
+ this.resourcesService = resourcesService;
2682
+ this.datepickerComponent = datepickerComponent;
2683
+ /**
2684
+ * Indicates whether to disable date validation on the datepicker input.
2685
+ * @default false
2686
+ */
2687
+ this.skyDatepickerNoValidate = false;
2688
+ this.dateFormatter = new SkyDateFormatter();
2689
+ this.ngUnsubscribe = new Subject();
2690
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
2691
+ this.onChange = (_) => { };
2692
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
2693
+ this.onTouched = () => { };
2694
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
2695
+ this.onValidatorChange = () => { };
2696
+ this.initialPlaceholder = this.adapter.getPlaceholder(this.elementRef);
2697
+ this.updatePlaceholder();
2698
+ this.localeProvider
2699
+ .getLocaleInfo()
2700
+ .pipe(takeUntil(this.ngUnsubscribe))
2701
+ .subscribe((localeInfo) => {
2702
+ SkyDateFormatter.setLocale(localeInfo.locale);
2703
+ this.preferredShortDateFormat =
2704
+ SkyDateFormatter.getPreferredShortDateFormat();
2705
+ this.applyDateFormat();
2706
+ });
2707
+ }
2708
+ /**
2709
+ * Specifies the date format for the input. Place this attribute on the `input` element
2710
+ * to override the default in the `SkyDatepickerConfigService`.
2711
+ * @default "MM/DD/YYYY"
2712
+ */
2713
+ set dateFormat(value) {
2714
+ /* istanbul ignore else */
2715
+ if (value !== this._dateFormat) {
2716
+ this._dateFormat = value;
2717
+ this.applyDateFormat();
2718
+ }
2719
+ }
2720
+ get dateFormat() {
2721
+ return (this._dateFormat ||
2722
+ this.configService.dateFormat ||
2723
+ this.preferredShortDateFormat);
2724
+ }
2725
+ /**
2726
+ * Indicates whether to disable the datepicker.
2727
+ * @default false
2728
+ */
2729
+ set disabled(value) {
2730
+ this._disabled = value;
2731
+ this.datepickerComponent.disabled = value;
2732
+ this.renderer.setProperty(this.elementRef.nativeElement, 'disabled', value);
2733
+ }
2734
+ get disabled() {
2735
+ return this._disabled || false;
2736
+ }
2737
+ /**
2738
+ * @internal
2739
+ * Indicates if the input element or any of its children have focus.
2740
+ */
2741
+ get inputIsFocused() {
2742
+ return this.adapter.elementIsFocused();
2743
+ }
2744
+ /**
2745
+ * Specifies the latest date that is available in the calendar. Place this attribute on
2746
+ * the `input` element to override the default in `SkyDatepickerConfigService`.
2747
+ */
2748
+ set maxDate(value) {
2749
+ this._maxDate = value;
2750
+ this.datepickerComponent.maxDate = this.maxDate;
2751
+ this.onValidatorChange();
2752
+ }
2753
+ get maxDate() {
2754
+ return this._maxDate || this.configService.maxDate;
2755
+ }
2756
+ /**
2757
+ * Specifies the earliest date that is available in the calendar. Place this attribute on
2758
+ * the `input` element to override the default in `SkyDatepickerConfigService`.
2759
+ */
2760
+ set minDate(value) {
2761
+ this._minDate = value;
2762
+ this.datepickerComponent.minDate = this.minDate;
2763
+ this.onValidatorChange();
2764
+ }
2765
+ get minDate() {
2766
+ return this._minDate || this.configService.minDate;
2767
+ }
2768
+ /**
2769
+ * Creates the datepicker input and calendar. Place this directive on an `input` element,
2770
+ * and wrap the input in a `sky-datepicker` component. The value that users select is driven
2771
+ * through the `ngModel` attribute specified on the `input` element.
2772
+ * @required
2773
+ */
2774
+ set skyDatepickerInput(value) {
2775
+ if (value) {
2776
+ console.warn('[Deprecation warning] You no longer need to provide a template reference variable ' +
2777
+ 'to the `skyDatepickerInput` attribute (this will be a breaking change in the next ' +
2778
+ 'major version release).\n' +
2779
+ 'Do this instead:\n' +
2780
+ '<sky-datepicker>\n <input skyDatepickerInput />\n</sky-datepicker>');
2781
+ }
2782
+ }
2783
+ /**
2784
+ * Specifies the starting day of the week in the calendar, where `0` sets the starting day
2785
+ * to Sunday. Place this attribute on the `input` element to override the default
2786
+ * in `SkyDatepickerConfigService`.
2787
+ * @default 0
2788
+ */
2789
+ set startingDay(value) {
2790
+ this._startingDay = value;
2791
+ this.datepickerComponent.startingDay = this.startingDay;
2792
+ this.onValidatorChange();
2793
+ }
2794
+ get startingDay() {
2795
+ return this._startingDay || this.configService.startingDay;
2796
+ }
2797
+ /**
2798
+ * Indicates whether the format of the date value must match the format from the `dateFormat` value.
2799
+ * If this property is `true` and the datepicker input directive cannot find an exact match, then
2800
+ * the input is marked as invalid.
2801
+ * If this property is `false` and the datepicker input directive cannot find an exact match, then
2802
+ * it attempts to format the string based on the [ISO 8601 standard format](https://www.iso.org/iso-8601-date-and-time-format.html).
2803
+ * @default false
2804
+ */
2805
+ set strict(value) {
2806
+ this._strict = value;
2807
+ }
2808
+ get strict() {
2809
+ return this._strict || false;
2810
+ }
2811
+ get value() {
2812
+ return this._value;
2813
+ }
2814
+ set value(value) {
2815
+ this.updateValue(value);
2816
+ }
2817
+ ngOnInit() {
2818
+ if (!this.datepickerComponent) {
2819
+ throw new Error('You must wrap the `skyDatepickerInput` directive within a ' +
2820
+ '`<sky-datepicker>` component!');
2821
+ }
2822
+ const element = this.elementRef.nativeElement;
2823
+ this.renderer.addClass(element, 'sky-form-control');
2824
+ const hasAriaLabel = element.getAttribute('aria-label');
2825
+ if (!hasAriaLabel) {
2826
+ this.resourcesService
2827
+ .getString('skyux_date_field_default_label')
2828
+ .pipe(takeUntil(this.ngUnsubscribe))
2829
+ .subscribe((value) => {
2830
+ this.renderer.setAttribute(element, 'aria-label', value);
2831
+ });
2832
+ }
2833
+ }
2834
+ ngAfterContentInit() {
2835
+ this.datepickerComponent.dateChange
2836
+ .pipe(distinctUntilChanged())
2837
+ .pipe(takeUntil(this.ngUnsubscribe))
2838
+ .subscribe((value) => {
2839
+ this.value = value;
2840
+ this.onTouched();
2841
+ });
2842
+ }
2843
+ ngAfterViewInit() {
2844
+ // This is needed to address a bug in Angular 4.
2845
+ // When a control value is set intially, its value is not represented on the view.
2846
+ // See: https://github.com/angular/angular/issues/13792
2847
+ // Of note is the parent check which allows us to determine if the form is reactive.
2848
+ // Without this check there is a changed before checked error
2849
+ /* istanbul ignore else */
2850
+ if (this.control && this.control.parent) {
2851
+ setTimeout(() => {
2852
+ this.control.setValue(this.value, {
2853
+ emitEvent: false,
2854
+ });
2855
+ this.changeDetector.markForCheck();
2856
+ });
2857
+ }
2858
+ this.adapter.init(this.elementRef);
2859
+ }
2860
+ ngOnDestroy() {
2861
+ this.ngUnsubscribe.next();
2862
+ this.ngUnsubscribe.complete();
2863
+ }
2864
+ onInputChange(event) {
2865
+ const value = event.target.value;
2866
+ if (this.skyDatepickerNoValidate) {
2867
+ this.onValueChange(value);
2868
+ return;
2869
+ }
2870
+ // Don't try to parse the string value into a Date value if it is malformed.
2871
+ if (this.isDateStringValid(value)) {
2872
+ this.onValueChange(value);
2873
+ return;
2874
+ }
2875
+ this._value = value;
2876
+ this.onChange(value);
2877
+ this.control.setErrors({
2878
+ skyDate: {
2879
+ invalid: true,
2880
+ },
2881
+ });
2882
+ }
2883
+ onInputBlur() {
2884
+ this.onTouched();
2885
+ }
2886
+ onInputKeyup() {
2887
+ this.control.markAsDirty();
2888
+ }
2889
+ writeValue(value) {
2890
+ this.updateValue(value, false);
2891
+ }
2892
+ validate(control) {
2893
+ if (!this.control) {
2894
+ this.control = control;
2895
+ }
2896
+ if (this.skyDatepickerNoValidate) {
2897
+ return;
2898
+ }
2899
+ const value = control.value;
2900
+ if (!value) {
2901
+ return;
2902
+ }
2903
+ const dateValue = this.getDateValue(value);
2904
+ const isDateValid = dateValue && this.dateFormatter.dateIsValid(dateValue);
2905
+ if (!isDateValid || !this.isDateStringValid(value)) {
2906
+ // Mark the invalid control as touched so that the input's invalid CSS styles appear.
2907
+ // (This is only required when the invalid value is set by the FormControl constructor.)
2908
+ this.control.markAsTouched();
2909
+ return {
2910
+ skyDate: {
2911
+ invalid: value,
2912
+ },
2913
+ };
2914
+ }
2915
+ const minDate = this.minDate;
2916
+ if (minDate && this.dateFormatter.dateIsValid(minDate) && value < minDate) {
2917
+ return {
2918
+ skyDate: {
2919
+ minDate,
2920
+ },
2921
+ };
2922
+ }
2923
+ const maxDate = this.maxDate;
2924
+ if (maxDate && this.dateFormatter.dateIsValid(maxDate) && value > maxDate) {
2925
+ return {
2926
+ skyDate: {
2927
+ maxDate,
2928
+ },
2929
+ };
2930
+ }
2931
+ }
2932
+ registerOnChange(fn) {
2933
+ this.onChange = fn;
2934
+ }
2935
+ registerOnTouched(fn) {
2936
+ this.onTouched = fn;
2937
+ }
2938
+ registerOnValidatorChange(fn) {
2939
+ this.onValidatorChange = fn;
2940
+ }
2941
+ setDisabledState(disabled) {
2942
+ this.disabled = disabled;
2943
+ this.datepickerComponent.disabled = disabled;
2944
+ }
2945
+ /**
2946
+ * Detects changes to the underlying input element's value and updates the ngModel accordingly.
2947
+ * This is useful if you need to update the ngModel value before the input element loses focus.
2948
+ */
2949
+ detectInputValueChange() {
2950
+ this.onValueChange(this.elementRef.nativeElement.value);
2951
+ }
2952
+ applyDateFormat() {
2953
+ this.updatePlaceholder();
2954
+ if (this.value) {
2955
+ const formattedDate = this.dateFormatter.format(this.value, this.dateFormat);
2956
+ this.setInputElementValue(formattedDate);
2957
+ this.changeDetector.markForCheck();
2958
+ }
2959
+ }
2960
+ onValueChange(newValue) {
2961
+ this.value = newValue;
2962
+ }
2963
+ setInputElementValue(value) {
2964
+ this.renderer.setProperty(this.elementRef.nativeElement, 'value', value);
2965
+ }
2966
+ getDateValue(value) {
2967
+ let dateValue;
2968
+ if (value instanceof Date) {
2969
+ dateValue = value;
2970
+ }
2971
+ else if (typeof value === 'string') {
2972
+ const date = this.dateFormatter.getDateFromString(value, this.dateFormat, this.strict);
2973
+ if (this.dateFormatter.dateIsValid(date)) {
2974
+ dateValue = date;
2975
+ }
2976
+ }
2977
+ return dateValue;
2978
+ }
2979
+ /**
2980
+ * Validates the input value to ensure it is formatted correctly.
2981
+ */
2982
+ isDateStringValid(value) {
2983
+ if (!value || typeof value !== 'string') {
2984
+ return true;
2985
+ }
2986
+ // Does the value only include digits, dashes, or slashes?
2987
+ const regexp = /^[\d/-]+$/;
2988
+ const isValid = regexp.test(value);
2989
+ if (isValid) {
2990
+ return true;
2991
+ }
2992
+ // If not, does it conform to the standard ISO format?
2993
+ const isValidIso = moment(value, moment.ISO_8601).isValid();
2994
+ return isValidIso;
2995
+ }
2996
+ updatePlaceholder() {
2997
+ if (!this.initialPlaceholder) {
2998
+ this.adapter.setPlaceholder(this.elementRef, this.dateFormat);
2999
+ }
3000
+ }
3001
+ /**
3002
+ * Update the value of the form control and input element
3003
+ * @param emitEvent Denotes if we emit an event to the consumer's form control. We do not want to do this if the value is being updated via a `setValue` call or a `patchValue` call as this is already handled by Angular.
3004
+ * In these cases we do not want to fire `onChange` as it will cause extra `valueChange` and `statusChange` events and the status of the form should not be affected by these changes.
3005
+ */
3006
+ updateValue(value, emitEvent = true) {
3007
+ var _a, _b;
3008
+ if (this._value === value) {
3009
+ return;
3010
+ }
3011
+ const dateValue = this.getDateValue(value);
3012
+ const areDatesEqual = this._value instanceof Date &&
3013
+ dateValue &&
3014
+ dateValue.getTime() === this._value.getTime();
3015
+ const isValidDateString = this.isDateStringValid(value);
3016
+ // If the string value supplied is malformed, do not set the value to its Date equivalent.
3017
+ // (JavaScript's Date parser will convert poorly formatted dates to Date objects, such as "abc 123", which isn't ideal.)
3018
+ if (!isValidDateString) {
3019
+ this._value = value;
3020
+ if (emitEvent) {
3021
+ this.onChange(this._value);
3022
+ }
3023
+ else {
3024
+ (_a = this.control) === null || _a === void 0 ? void 0 : _a.setValue(this._value, { emitEvent: false });
3025
+ }
3026
+ this.datepickerComponent.selectedDate = this._value;
3027
+ }
3028
+ else if (dateValue !== this._value || !areDatesEqual) {
3029
+ this._value = dateValue || value;
3030
+ if (emitEvent) {
3031
+ this.onChange(this._value);
3032
+ }
3033
+ else {
3034
+ (_b = this.control) === null || _b === void 0 ? void 0 : _b.setValue(this._value, { emitEvent: false });
3035
+ }
3036
+ this.datepickerComponent.selectedDate = this._value;
3037
+ }
3038
+ if (dateValue && isValidDateString) {
3039
+ const formattedDate = this.dateFormatter.format(dateValue, this.dateFormat);
3040
+ this.setInputElementValue(formattedDate);
3041
+ }
3042
+ else {
3043
+ this.setInputElementValue(value || '');
3044
+ }
3045
+ }
3046
+ }
3047
+ SkyDatepickerInputDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerInputDirective, deps: [{ token: SkyDatepickerAdapterService }, { token: i0.ChangeDetectorRef }, { token: SkyDatepickerConfigService }, { token: i0.ElementRef }, { token: i3.SkyAppLocaleProvider }, { token: i0.Renderer2 }, { token: i3.SkyLibResourcesService }, { token: SkyDatepickerComponent, optional: true }], target: i0.ɵɵFactoryTarget.Directive });
3048
+ SkyDatepickerInputDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.2.7", type: SkyDatepickerInputDirective, selector: "[skyDatepickerInput]", inputs: { dateFormat: "dateFormat", disabled: "disabled", maxDate: "maxDate", minDate: "minDate", skyDatepickerInput: "skyDatepickerInput", skyDatepickerNoValidate: "skyDatepickerNoValidate", startingDay: "startingDay", strict: "strict" }, host: { listeners: { "change": "onInputChange($event)", "blur": "onInputBlur()", "keyup": "onInputKeyup()" } }, providers: [
3049
+ SKY_DATEPICKER_VALUE_ACCESSOR,
3050
+ SKY_DATEPICKER_VALIDATOR,
3051
+ SkyDatepickerAdapterService,
3052
+ ], ngImport: i0 });
3053
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerInputDirective, decorators: [{
3054
+ type: Directive,
3055
+ args: [{
3056
+ selector: '[skyDatepickerInput]',
3057
+ providers: [
3058
+ SKY_DATEPICKER_VALUE_ACCESSOR,
3059
+ SKY_DATEPICKER_VALIDATOR,
3060
+ SkyDatepickerAdapterService,
3061
+ ],
3062
+ }]
3063
+ }], ctorParameters: function () {
3064
+ return [{ type: SkyDatepickerAdapterService }, { type: i0.ChangeDetectorRef }, { type: SkyDatepickerConfigService }, { type: i0.ElementRef }, { type: i3.SkyAppLocaleProvider }, { type: i0.Renderer2 }, { type: i3.SkyLibResourcesService }, { type: SkyDatepickerComponent, decorators: [{
3065
+ type: Optional
3066
+ }] }];
3067
+ }, propDecorators: { dateFormat: [{
3068
+ type: Input
3069
+ }], disabled: [{
3070
+ type: Input
3071
+ }], maxDate: [{
3072
+ type: Input
3073
+ }], minDate: [{
3074
+ type: Input
3075
+ }], skyDatepickerInput: [{
3076
+ type: Input
3077
+ }], skyDatepickerNoValidate: [{
3078
+ type: Input
3079
+ }], startingDay: [{
3080
+ type: Input
3081
+ }], strict: [{
3082
+ type: Input
3083
+ }], onInputChange: [{
3084
+ type: HostListener,
3085
+ args: ['change', ['$event']]
3086
+ }], onInputBlur: [{
3087
+ type: HostListener,
3088
+ args: ['blur']
3089
+ }], onInputKeyup: [{
3090
+ type: HostListener,
3091
+ args: ['keyup']
3092
+ }] } });
3093
+
3094
+ class SkyDatepickerModule {
3095
+ }
3096
+ SkyDatepickerModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
3097
+ SkyDatepickerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerModule, declarations: [SkyDatepickerCalendarComponent,
3098
+ SkyDatepickerCalendarInnerComponent,
3099
+ SkyDayPickerComponent,
3100
+ SkyMonthPickerComponent,
3101
+ SkyYearPickerComponent,
3102
+ SkyDatepickerComponent,
3103
+ SkyDatepickerInputDirective,
3104
+ SkyFuzzyDatepickerInputDirective,
3105
+ SkyDayPickerCellComponent,
3106
+ SkyDayPickerButtonComponent], imports: [CommonModule,
3107
+ SkyI18nModule,
3108
+ FormsModule,
3109
+ SkyIconModule,
3110
+ SkyDatetimeResourcesModule,
3111
+ SkyAffixModule,
3112
+ SkyOverlayModule,
3113
+ SkyThemeModule,
3114
+ SkyPopoverModule,
3115
+ SkyWaitModule], exports: [SkyDatepickerCalendarComponent,
3116
+ SkyDatepickerComponent,
3117
+ SkyDatepickerInputDirective,
3118
+ SkyFuzzyDatepickerInputDirective] });
3119
+ SkyDatepickerModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerModule, providers: [SkyDatepickerService], imports: [[
3120
+ CommonModule,
3121
+ SkyI18nModule,
3122
+ FormsModule,
3123
+ SkyIconModule,
3124
+ SkyDatetimeResourcesModule,
3125
+ SkyAffixModule,
3126
+ SkyOverlayModule,
3127
+ SkyThemeModule,
3128
+ SkyPopoverModule,
3129
+ SkyWaitModule,
3130
+ ]] });
3131
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDatepickerModule, decorators: [{
3132
+ type: NgModule,
3133
+ args: [{
3134
+ declarations: [
3135
+ SkyDatepickerCalendarComponent,
3136
+ SkyDatepickerCalendarInnerComponent,
3137
+ SkyDayPickerComponent,
3138
+ SkyMonthPickerComponent,
3139
+ SkyYearPickerComponent,
3140
+ SkyDatepickerComponent,
3141
+ SkyDatepickerInputDirective,
3142
+ SkyFuzzyDatepickerInputDirective,
3143
+ SkyDayPickerCellComponent,
3144
+ SkyDayPickerButtonComponent,
3145
+ ],
3146
+ imports: [
3147
+ CommonModule,
3148
+ SkyI18nModule,
3149
+ FormsModule,
3150
+ SkyIconModule,
3151
+ SkyDatetimeResourcesModule,
3152
+ SkyAffixModule,
3153
+ SkyOverlayModule,
3154
+ SkyThemeModule,
3155
+ SkyPopoverModule,
3156
+ SkyWaitModule,
3157
+ ],
3158
+ exports: [
3159
+ SkyDatepickerCalendarComponent,
3160
+ SkyDatepickerComponent,
3161
+ SkyDatepickerInputDirective,
3162
+ SkyFuzzyDatepickerInputDirective,
3163
+ ],
3164
+ providers: [SkyDatepickerService],
3165
+ }]
3166
+ }] });
3167
+
3168
+ /**
3169
+ * Need to add the following to classes which contain static methods.
3170
+ * See: https://github.com/ng-packagr/ng-packagr/issues/641
3171
+ * @internal
3172
+ * @dynamic
3173
+ */
3174
+ class SkyDateRangeRelativeValue {
3175
+ static get today() {
3176
+ const today = new Date();
3177
+ return {
3178
+ startDate: today,
3179
+ endDate: today,
3180
+ };
3181
+ }
3182
+ static get tomorrow() {
3183
+ const tomorrow = new Date();
3184
+ tomorrow.setDate(tomorrow.getDate() + 1);
3185
+ return {
3186
+ startDate: tomorrow,
3187
+ endDate: tomorrow,
3188
+ };
3189
+ }
3190
+ static get yesterday() {
3191
+ const yesterday = new Date();
3192
+ yesterday.setDate(yesterday.getDate() - 1);
3193
+ return {
3194
+ startDate: yesterday,
3195
+ endDate: yesterday,
3196
+ };
3197
+ }
3198
+ /**
3199
+ * A date range starting with the nearest past Sunday and ending with the following Saturday.
3200
+ */
3201
+ static get thisWeek() {
3202
+ const startDate = new Date();
3203
+ startDate.setDate(startDate.getDate() - startDate.getDay());
3204
+ const endDate = new Date();
3205
+ endDate.setDate(endDate.getDate() - endDate.getDay() + 6);
3206
+ return {
3207
+ startDate,
3208
+ endDate,
3209
+ };
3210
+ }
3211
+ /**
3212
+ * A date range starting with the nearest upcoming Sunday and ending with the following Saturday.
3213
+ */
3214
+ static get nextWeek() {
3215
+ const startDate = new Date();
3216
+ startDate.setDate(startDate.getDate() - startDate.getDay() + 7);
3217
+ const endDate = new Date();
3218
+ endDate.setDate(endDate.getDate() - endDate.getDay() + 13);
3219
+ return {
3220
+ startDate,
3221
+ endDate,
3222
+ };
3223
+ }
3224
+ static get lastWeek() {
3225
+ const startDate = new Date();
3226
+ startDate.setDate(startDate.getDate() - startDate.getDay() - 7);
3227
+ const endDate = new Date();
3228
+ endDate.setDate(endDate.getDate() - endDate.getDay() - 1);
3229
+ return {
3230
+ startDate,
3231
+ endDate,
3232
+ };
3233
+ }
3234
+ static get thisMonth() {
3235
+ const startDate = new Date();
3236
+ startDate.setDate(1);
3237
+ const endDate = new Date();
3238
+ endDate.setMonth(endDate.getMonth() + 1);
3239
+ endDate.setDate(0);
3240
+ return {
3241
+ startDate,
3242
+ endDate,
3243
+ };
3244
+ }
3245
+ static get nextMonth() {
3246
+ const startDate = new Date();
3247
+ startDate.setDate(1);
3248
+ startDate.setMonth(startDate.getMonth() + 1);
3249
+ const endDate = new Date();
3250
+ endDate.setDate(1);
3251
+ endDate.setMonth(endDate.getMonth() + 2);
3252
+ endDate.setDate(0);
3253
+ return {
3254
+ startDate,
3255
+ endDate,
3256
+ };
3257
+ }
3258
+ static get lastMonth() {
3259
+ const startDate = new Date();
3260
+ // First, set the day of the month to zero,
3261
+ // which points to the last day of the previous month.
3262
+ startDate.setDate(0);
3263
+ // Finally, set the day of the month to 1.
3264
+ startDate.setDate(1);
3265
+ const endDate = new Date();
3266
+ endDate.setDate(0);
3267
+ return {
3268
+ startDate,
3269
+ endDate,
3270
+ };
3271
+ }
3272
+ static get thisQuarter() {
3273
+ const startDate = new Date();
3274
+ const endDate = new Date();
3275
+ const currentMonth = startDate.getMonth();
3276
+ const quarterStartMonth = SkyDateRangeRelativeValue.getQuarterStartMonth(currentMonth);
3277
+ startDate.setMonth(quarterStartMonth);
3278
+ startDate.setDate(1);
3279
+ endDate.setMonth(quarterStartMonth + 3);
3280
+ endDate.setDate(0);
3281
+ return {
3282
+ startDate,
3283
+ endDate,
3284
+ };
3285
+ }
3286
+ static get nextQuarter() {
3287
+ const startDate = new Date();
3288
+ const endDate = new Date();
3289
+ const currentMonth = startDate.getMonth();
3290
+ const quarterStartMonth = SkyDateRangeRelativeValue.getQuarterStartMonth(currentMonth);
3291
+ startDate.setMonth(quarterStartMonth + 3);
3292
+ startDate.setDate(1);
3293
+ endDate.setMonth(quarterStartMonth + 6);
3294
+ endDate.setDate(0);
3295
+ return {
3296
+ startDate,
3297
+ endDate,
3298
+ };
3299
+ }
3300
+ static get lastQuarter() {
3301
+ const startDate = new Date();
3302
+ startDate.setDate(1);
3303
+ const endDate = new Date();
3304
+ endDate.setDate(1);
3305
+ const currentMonth = startDate.getMonth();
3306
+ const quarterStartMonth = SkyDateRangeRelativeValue.getQuarterStartMonth(currentMonth);
3307
+ startDate.setMonth(quarterStartMonth - 3);
3308
+ startDate.setDate(1);
3309
+ endDate.setMonth(quarterStartMonth);
3310
+ endDate.setDate(0);
3311
+ return {
3312
+ startDate,
3313
+ endDate,
3314
+ };
3315
+ }
3316
+ static get thisCalendarYear() {
3317
+ const startDate = new Date();
3318
+ startDate.setDate(1);
3319
+ startDate.setMonth(0);
3320
+ const endDate = new Date();
3321
+ endDate.setDate(1);
3322
+ endDate.setMonth(0);
3323
+ endDate.setFullYear(endDate.getFullYear() + 1);
3324
+ endDate.setDate(0);
3325
+ return {
3326
+ startDate,
3327
+ endDate,
3328
+ };
3329
+ }
3330
+ static get nextCalendarYear() {
3331
+ const startDate = new Date();
3332
+ startDate.setDate(1);
3333
+ startDate.setMonth(0);
3334
+ startDate.setFullYear(startDate.getFullYear() + 1);
3335
+ const endDate = new Date();
3336
+ endDate.setDate(1);
3337
+ endDate.setMonth(0);
3338
+ endDate.setFullYear(startDate.getFullYear() + 1);
3339
+ endDate.setDate(0);
3340
+ return {
3341
+ startDate,
3342
+ endDate,
3343
+ };
3344
+ }
3345
+ static get lastCalendarYear() {
3346
+ const startDate = new Date();
3347
+ startDate.setDate(1);
3348
+ startDate.setMonth(0);
3349
+ startDate.setFullYear(startDate.getFullYear() - 1);
3350
+ const endDate = new Date();
3351
+ endDate.setDate(1);
3352
+ endDate.setMonth(0);
3353
+ endDate.setDate(0);
3354
+ return {
3355
+ startDate,
3356
+ endDate,
3357
+ };
3358
+ }
3359
+ static get thisFiscalYear() {
3360
+ const start = new Date();
3361
+ start.setDate(1);
3362
+ return SkyDateRangeRelativeValue.getClosestFiscalYearRange(start);
3363
+ }
3364
+ static get nextFiscalYear() {
3365
+ const start = new Date();
3366
+ start.setDate(1);
3367
+ start.setFullYear(start.getFullYear() + 1);
3368
+ return SkyDateRangeRelativeValue.getClosestFiscalYearRange(start);
3369
+ }
3370
+ static get lastFiscalYear() {
3371
+ const start = new Date();
3372
+ start.setDate(1);
3373
+ start.setFullYear(start.getFullYear() - 1);
3374
+ return SkyDateRangeRelativeValue.getClosestFiscalYearRange(start);
3375
+ }
3376
+ static getQuarterStartMonth(currentMonth) {
3377
+ let month;
3378
+ if (currentMonth < 3) {
3379
+ month = 0;
3380
+ }
3381
+ else if (currentMonth < 6) {
3382
+ month = 3;
3383
+ }
3384
+ else if (currentMonth < 9) {
3385
+ month = 6;
3386
+ }
3387
+ else {
3388
+ month = 9;
3389
+ }
3390
+ return month;
3391
+ }
3392
+ /**
3393
+ * Return a fiscal year based on a start date.
3394
+ * (The fiscal year starts in October and continues through to next September.)
3395
+ */
3396
+ static getClosestFiscalYearRange(startDate) {
3397
+ const endDate = new Date(startDate);
3398
+ if (startDate.getMonth() >= 9) {
3399
+ startDate.setMonth(9);
3400
+ endDate.setFullYear(startDate.getFullYear() + 1);
3401
+ endDate.setMonth(9);
3402
+ endDate.setDate(0);
3403
+ }
3404
+ else {
3405
+ startDate.setFullYear(startDate.getFullYear() - 1);
3406
+ startDate.setMonth(9);
3407
+ endDate.setMonth(9);
3408
+ endDate.setDate(0);
3409
+ }
3410
+ return {
3411
+ startDate,
3412
+ endDate,
3413
+ };
3414
+ }
3415
+ }
3416
+
3417
+ const SKY_DEFAULT_CALCULATOR_CONFIGS = [
3418
+ {
3419
+ calculatorId: SkyDateRangeCalculatorId.AnyTime,
3420
+ type: SkyDateRangeCalculatorType.Relative,
3421
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_any_time',
3422
+ getValue: (startDate, endDate) => ({ startDate, endDate }),
3423
+ },
3424
+ {
3425
+ calculatorId: SkyDateRangeCalculatorId.Before,
3426
+ type: SkyDateRangeCalculatorType.Before,
3427
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_before',
3428
+ getValue: (startDate, endDate) => ({ startDate, endDate }),
3429
+ },
3430
+ {
3431
+ calculatorId: SkyDateRangeCalculatorId.After,
3432
+ type: SkyDateRangeCalculatorType.After,
3433
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_after',
3434
+ getValue: (startDate, endDate) => ({ startDate, endDate }),
3435
+ },
3436
+ {
3437
+ calculatorId: SkyDateRangeCalculatorId.SpecificRange,
3438
+ type: SkyDateRangeCalculatorType.Range,
3439
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_specific_range',
3440
+ getValue: (startDate, endDate) => ({ startDate, endDate }),
3441
+ validate: (value) => {
3442
+ if (value.startDate &&
3443
+ value.endDate &&
3444
+ value.startDate > value.endDate) {
3445
+ return {
3446
+ endDateBeforeStartDate: true,
3447
+ };
3448
+ }
3449
+ },
3450
+ },
3451
+ {
3452
+ calculatorId: SkyDateRangeCalculatorId.LastFiscalYear,
3453
+ type: SkyDateRangeCalculatorType.Relative,
3454
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_last_fiscal_year',
3455
+ getValue: () => SkyDateRangeRelativeValue.lastFiscalYear,
3456
+ },
3457
+ {
3458
+ calculatorId: SkyDateRangeCalculatorId.LastMonth,
3459
+ type: SkyDateRangeCalculatorType.Relative,
3460
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_last_month',
3461
+ getValue: () => SkyDateRangeRelativeValue.lastMonth,
3462
+ },
3463
+ {
3464
+ calculatorId: SkyDateRangeCalculatorId.LastQuarter,
3465
+ type: SkyDateRangeCalculatorType.Relative,
3466
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_last_quarter',
3467
+ getValue: () => SkyDateRangeRelativeValue.lastQuarter,
3468
+ },
3469
+ {
3470
+ calculatorId: SkyDateRangeCalculatorId.LastWeek,
3471
+ type: SkyDateRangeCalculatorType.Relative,
3472
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_last_week',
3473
+ getValue: () => SkyDateRangeRelativeValue.lastWeek,
3474
+ },
3475
+ {
3476
+ calculatorId: SkyDateRangeCalculatorId.LastCalendarYear,
3477
+ type: SkyDateRangeCalculatorType.Relative,
3478
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_last_calendar_year',
3479
+ getValue: () => SkyDateRangeRelativeValue.lastCalendarYear,
3480
+ },
3481
+ {
3482
+ calculatorId: SkyDateRangeCalculatorId.NextFiscalYear,
3483
+ type: SkyDateRangeCalculatorType.Relative,
3484
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_next_fiscal_year',
3485
+ getValue: () => SkyDateRangeRelativeValue.nextFiscalYear,
3486
+ },
3487
+ {
3488
+ calculatorId: SkyDateRangeCalculatorId.NextMonth,
3489
+ type: SkyDateRangeCalculatorType.Relative,
3490
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_next_month',
3491
+ getValue: () => SkyDateRangeRelativeValue.nextMonth,
3492
+ },
3493
+ {
3494
+ calculatorId: SkyDateRangeCalculatorId.NextQuarter,
3495
+ type: SkyDateRangeCalculatorType.Relative,
3496
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_next_quarter',
3497
+ getValue: () => SkyDateRangeRelativeValue.nextQuarter,
3498
+ },
3499
+ {
3500
+ calculatorId: SkyDateRangeCalculatorId.NextWeek,
3501
+ type: SkyDateRangeCalculatorType.Relative,
3502
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_next_week',
3503
+ getValue: () => SkyDateRangeRelativeValue.nextWeek,
3504
+ },
3505
+ {
3506
+ calculatorId: SkyDateRangeCalculatorId.NextCalendarYear,
3507
+ type: SkyDateRangeCalculatorType.Relative,
3508
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_next_calendar_year',
3509
+ getValue: () => SkyDateRangeRelativeValue.nextCalendarYear,
3510
+ },
3511
+ {
3512
+ calculatorId: SkyDateRangeCalculatorId.ThisFiscalYear,
3513
+ type: SkyDateRangeCalculatorType.Relative,
3514
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_this_fiscal_year',
3515
+ getValue: () => SkyDateRangeRelativeValue.thisFiscalYear,
3516
+ },
3517
+ {
3518
+ calculatorId: SkyDateRangeCalculatorId.ThisMonth,
3519
+ type: SkyDateRangeCalculatorType.Relative,
3520
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_this_month',
3521
+ getValue: () => SkyDateRangeRelativeValue.thisMonth,
3522
+ },
3523
+ {
3524
+ calculatorId: SkyDateRangeCalculatorId.ThisQuarter,
3525
+ type: SkyDateRangeCalculatorType.Relative,
3526
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_this_quarter',
3527
+ getValue: () => SkyDateRangeRelativeValue.thisQuarter,
3528
+ },
3529
+ {
3530
+ calculatorId: SkyDateRangeCalculatorId.ThisWeek,
3531
+ type: SkyDateRangeCalculatorType.Relative,
3532
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_this_week',
3533
+ getValue: () => SkyDateRangeRelativeValue.thisWeek,
3534
+ },
3535
+ {
3536
+ calculatorId: SkyDateRangeCalculatorId.ThisCalendarYear,
3537
+ type: SkyDateRangeCalculatorType.Relative,
3538
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_this_calendar_year',
3539
+ getValue: () => SkyDateRangeRelativeValue.thisCalendarYear,
3540
+ },
3541
+ {
3542
+ calculatorId: SkyDateRangeCalculatorId.Today,
3543
+ type: SkyDateRangeCalculatorType.Relative,
3544
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_today',
3545
+ getValue: () => SkyDateRangeRelativeValue.today,
3546
+ },
3547
+ {
3548
+ calculatorId: SkyDateRangeCalculatorId.Tomorrow,
3549
+ type: SkyDateRangeCalculatorType.Relative,
3550
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_tomorrow',
3551
+ getValue: () => SkyDateRangeRelativeValue.tomorrow,
3552
+ },
3553
+ {
3554
+ calculatorId: SkyDateRangeCalculatorId.Yesterday,
3555
+ type: SkyDateRangeCalculatorType.Relative,
3556
+ shortDescriptionResourceKey: 'skyux_date_range_picker_format_label_yesterday',
3557
+ getValue: () => SkyDateRangeRelativeValue.yesterday,
3558
+ },
3559
+ ];
3560
+
3561
+ /**
3562
+ * Creates and manages `SkyDateRangeCalculator` instances.
3563
+ */
3564
+ class SkyDateRangeService {
3565
+ constructor(resourcesService) {
3566
+ this.resourcesService = resourcesService;
3567
+ this.calculatorReadyStream = new BehaviorSubject(false);
3568
+ this.calculatorConfigs = {};
3569
+ this.calculators = [];
3570
+ this.createDefaultCalculators();
3571
+ }
3572
+ /**
3573
+ * Creates a custom date range calculator.
3574
+ * @param config The calculator config.
3575
+ */
3576
+ createCalculator(config) {
3577
+ const newId = SkyDateRangeService.lastId++;
3578
+ const calculator = new SkyDateRangeCalculator(newId, config);
3579
+ this.calculators.push(calculator);
3580
+ return calculator;
3581
+ }
3582
+ /**
3583
+ * Returns calculators from an array of calculator IDs.
3584
+ * @param ids The array of calculator IDs.
3585
+ */
3586
+ getCalculators(ids) {
3587
+ const promises = ids.map((id) => {
3588
+ return this.getCalculatorById(id);
3589
+ });
3590
+ return Promise.all(promises);
3591
+ }
3592
+ /**
3593
+ * Returns a calculator from a calculator ID.
3594
+ * @param id The calculator ID.
3595
+ */
3596
+ getCalculatorById(id) {
3597
+ const calculatorId = parseInt(id, 10);
3598
+ const found = this.calculators.find((calculator) => {
3599
+ return calculator.calculatorId === calculatorId;
3600
+ });
3601
+ return new Promise((resolve, reject) => {
3602
+ if (!found) {
3603
+ reject(new Error(`A calculator with the ID ${id} was not found.`));
3604
+ return;
3605
+ }
3606
+ this.calculatorReadyStream.pipe(first()).subscribe(() => {
3607
+ resolve(found);
3608
+ });
3609
+ });
3610
+ }
3611
+ createDefaultCalculators() {
3612
+ const tasks = [];
3613
+ // Get resource strings for short descriptions.
3614
+ SKY_DEFAULT_CALCULATOR_CONFIGS.forEach((defaultConfig) => {
3615
+ const config = {
3616
+ getValue: defaultConfig.getValue,
3617
+ validate: defaultConfig.validate,
3618
+ shortDescription: '',
3619
+ type: defaultConfig.type,
3620
+ };
3621
+ tasks.push(this.resourcesService
3622
+ .getString(defaultConfig.shortDescriptionResourceKey)
3623
+ .pipe(first(), map((value) => {
3624
+ config.shortDescription = value;
3625
+ })));
3626
+ this.calculatorConfigs[defaultConfig.calculatorId] = config;
3627
+ });
3628
+ forkJoin(tasks)
3629
+ .pipe(first())
3630
+ .subscribe(() => {
3631
+ const calculatorIds = Object.keys(this.calculatorConfigs);
3632
+ const calculators = calculatorIds.map((calculatorId) => {
3633
+ const id = parseInt(calculatorId, 10);
3634
+ return new SkyDateRangeCalculator(id, this.calculatorConfigs[id]);
3635
+ });
3636
+ this.calculators = calculators;
3637
+ this.calculatorReadyStream.next(true);
3638
+ });
3639
+ }
3640
+ }
3641
+ // Start the count higher than the number of available values
3642
+ // provided in the SkyDateRangeCalculatorId enum.
3643
+ SkyDateRangeService.lastId = 1000;
3644
+ SkyDateRangeService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDateRangeService, deps: [{ token: i3.SkyLibResourcesService }], target: i0.ɵɵFactoryTarget.Injectable });
3645
+ SkyDateRangeService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDateRangeService });
3646
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDateRangeService, decorators: [{
3647
+ type: Injectable
3648
+ }], ctorParameters: function () { return [{ type: i3.SkyLibResourcesService }]; } });
3649
+
3650
+ /* tslint:disable:no-forward-ref no-use-before-declare */
3651
+ const SKY_DATE_RANGE_PICKER_VALUE_ACCESSOR = {
3652
+ provide: NG_VALUE_ACCESSOR,
3653
+ useExisting: forwardRef(() => SkyDateRangePickerComponent),
3654
+ multi: true,
3655
+ };
3656
+ const SKY_DATE_RANGE_PICKER_VALIDATOR = {
3657
+ provide: NG_VALIDATORS,
3658
+ useExisting: forwardRef(() => SkyDateRangePickerComponent),
3659
+ multi: true,
3660
+ };
3661
+ /* tslint:enable */
3662
+ let uniqueId = 0;
3663
+ /**
3664
+ * Acts as a form control with a form model of type `SkyDateRangeCalculation`.
3665
+ * @example
3666
+ * ```
3667
+ * <sky-date-range-picker
3668
+ * formControlName="myPicker"
3669
+ * >
3670
+ * </sky-date-range-picker>
3671
+ * ```
3672
+ */
3673
+ class SkyDateRangePickerComponent {
3674
+ constructor(changeDetector, dateRangeService, formBuilder, localeProvider, windowRef, ngZone, themeSvc) {
3675
+ this.changeDetector = changeDetector;
3676
+ this.dateRangeService = dateRangeService;
3677
+ this.formBuilder = formBuilder;
3678
+ this.localeProvider = localeProvider;
3679
+ this.windowRef = windowRef;
3680
+ this.ngZone = ngZone;
3681
+ /**
3682
+ * Indicates whether to require users to specify a start date.
3683
+ * @default false
3684
+ */
3685
+ this.startDateRequired = false;
3686
+ /**
3687
+ * Indicates whether to require users to specify a end date.
3688
+ * @default false
3689
+ */
3690
+ this.endDateRequired = false;
3691
+ this.dateRangePickerId = `sky-date-range-picker-${uniqueId++}`;
3692
+ this.isReady = false;
3693
+ this.showEndDatePicker = false;
3694
+ this.showStartDatePicker = false;
3695
+ this.ngUnsubscribe = new Subject();
3696
+ this._disabled = false;
3697
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
3698
+ this.onChange = (_) => { };
3699
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
3700
+ this.onTouched = () => { };
3701
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
3702
+ this.onValidatorChange = () => { };
3703
+ this.localeProvider
3704
+ .getLocaleInfo()
3705
+ .pipe(takeUntil(this.ngUnsubscribe))
3706
+ .subscribe((localeInfo) => {
3707
+ SkyDateFormatter.setLocale(localeInfo.locale);
3708
+ this.preferredShortDateFormat =
3709
+ SkyDateFormatter.getPreferredShortDateFormat();
3710
+ });
3711
+ // Update icons when theme changes.
3712
+ /* istanbul ignore next */
3713
+ themeSvc === null || themeSvc === void 0 ? void 0 : themeSvc.settingsChange.pipe(takeUntil(this.ngUnsubscribe)).subscribe(() => {
3714
+ this.changeDetector.markForCheck();
3715
+ });
3716
+ }
3717
+ /**
3718
+ * Specifies IDs for the date range options to include in the picker's dropdown.
3719
+ * The options specify calculator objects that return two `Date` objects to represent date ranges.
3720
+ * By default, this property includes all `SkyDateRangeCalculatorId` values.
3721
+ */
3722
+ set calculatorIds(value) {
3723
+ this._calculatorIds = value;
3724
+ }
3725
+ get calculatorIds() {
3726
+ return (this._calculatorIds || [
3727
+ SkyDateRangeCalculatorId.AnyTime,
3728
+ SkyDateRangeCalculatorId.Before,
3729
+ SkyDateRangeCalculatorId.After,
3730
+ SkyDateRangeCalculatorId.SpecificRange,
3731
+ SkyDateRangeCalculatorId.Yesterday,
3732
+ SkyDateRangeCalculatorId.Today,
3733
+ SkyDateRangeCalculatorId.Tomorrow,
3734
+ SkyDateRangeCalculatorId.LastWeek,
3735
+ SkyDateRangeCalculatorId.ThisWeek,
3736
+ SkyDateRangeCalculatorId.NextWeek,
3737
+ SkyDateRangeCalculatorId.LastMonth,
3738
+ SkyDateRangeCalculatorId.ThisMonth,
3739
+ SkyDateRangeCalculatorId.NextMonth,
3740
+ SkyDateRangeCalculatorId.LastQuarter,
3741
+ SkyDateRangeCalculatorId.ThisQuarter,
3742
+ SkyDateRangeCalculatorId.NextQuarter,
3743
+ SkyDateRangeCalculatorId.LastCalendarYear,
3744
+ SkyDateRangeCalculatorId.ThisCalendarYear,
3745
+ SkyDateRangeCalculatorId.NextCalendarYear,
3746
+ SkyDateRangeCalculatorId.LastFiscalYear,
3747
+ SkyDateRangeCalculatorId.ThisFiscalYear,
3748
+ SkyDateRangeCalculatorId.NextFiscalYear,
3749
+ ]);
3750
+ }
3751
+ /**
3752
+ * Specifies a date format for
3753
+ * [the `sky-datepicker` components](https://developer.blackbaud.com/skyux/components/datepicker)
3754
+ * that make up the date range picker. The text input is a composite component of
3755
+ * up to two `sky-datepicker` components.
3756
+ * @default "MM/DD/YYYY"
3757
+ */
3758
+ set dateFormat(value) {
3759
+ this._dateFormat = value;
3760
+ }
3761
+ get dateFormat() {
3762
+ return this._dateFormat || this.preferredShortDateFormat;
3763
+ }
3764
+ /**
3765
+ * Indicates whether to disable the date range picker.
3766
+ * @default false
3767
+ */
3768
+ set disabled(value) {
3769
+ this._disabled = value;
3770
+ if (this.formGroup) {
3771
+ if (this._disabled) {
3772
+ this.formGroup.disable();
3773
+ }
3774
+ else {
3775
+ this.formGroup.enable();
3776
+ }
3777
+ }
3778
+ this.changeDetector.markForCheck();
3779
+ }
3780
+ get disabled() {
3781
+ return this._disabled;
3782
+ }
3783
+ get startDateLabelResourceKey() {
3784
+ if (this.selectedCalculator.type === SkyDateRangeCalculatorType.Range) {
3785
+ return 'skyux_date_range_picker_start_date_label';
3786
+ }
3787
+ return 'skyux_date_range_picker_after_date_label';
3788
+ }
3789
+ get endDateLabelResourceKey() {
3790
+ if (this.selectedCalculator.type === SkyDateRangeCalculatorType.Range) {
3791
+ return 'skyux_date_range_picker_end_date_label';
3792
+ }
3793
+ return 'skyux_date_range_picker_before_date_label';
3794
+ }
3795
+ get selectedCalculator() {
3796
+ return this.getCalculatorById(this.value.calculatorId);
3797
+ }
3798
+ get calculatorIdControl() {
3799
+ return this.formGroup.get('calculatorId');
3800
+ }
3801
+ get defaultCalculator() {
3802
+ return this.calculators[0];
3803
+ }
3804
+ get defaultValue() {
3805
+ return this.defaultCalculator.getValue();
3806
+ }
3807
+ get endDateControl() {
3808
+ return this.formGroup.get('endDate');
3809
+ }
3810
+ get startDateControl() {
3811
+ return this.formGroup.get('startDate');
3812
+ }
3813
+ get value() {
3814
+ if (this._value && this._value.calculatorId !== undefined) {
3815
+ return this._value;
3816
+ }
3817
+ return this.defaultValue;
3818
+ }
3819
+ ngOnInit() {
3820
+ this.createForm();
3821
+ this.updateCalculators().then(() => {
3822
+ this.addEventListeners();
3823
+ this.isReady = true;
3824
+ this.showRelevantFormFields();
3825
+ // We need to let Angular be stable and have rendered the components prior to setting the values and form controls. This ensures all initial validation will be ran correctly.
3826
+ this.ngZone.onStable.pipe(first()).subscribe(() => {
3827
+ // Fill in any unprovided values after the calculators have been initialized.
3828
+ // For example, if the control is initialized with only the `calculatorId`,
3829
+ // allow the calculator to fill in the missing start and end dates.
3830
+ const { startDate, endDate } = this.value;
3831
+ const defaultValue = this.selectedCalculator.getValue(startDate, endDate);
3832
+ const newValue = Object.assign({}, defaultValue, this.value);
3833
+ this.setValue(newValue, false);
3834
+ this.resetFormGroupValue();
3835
+ // This is needed to address a bug in Angular 4.
3836
+ // When a control value is set intially, its value is not represented on the view.
3837
+ // See: https://github.com/angular/angular/issues/13792
3838
+ /* istanbul ignore else */
3839
+ if (this.control) {
3840
+ this.control.setValue(this.value, {
3841
+ emitEvent: false,
3842
+ });
3843
+ }
3844
+ });
3845
+ });
3846
+ }
3847
+ ngOnChanges(changes) {
3848
+ if (changes.calculatorIds && changes.calculatorIds.firstChange === false) {
3849
+ this.updateCalculators().then(() => {
3850
+ const id = this.calculatorIdControl.value;
3851
+ // Maintain the currently selected values if the calculators change after
3852
+ // a value has been chosen.
3853
+ const found = this.calculators.find((calculator) => {
3854
+ return calculator.calculatorId === id;
3855
+ });
3856
+ /* istanbul ignore else */
3857
+ if (!found) {
3858
+ const newValue = this.defaultCalculator.getValue();
3859
+ this.setValue(newValue);
3860
+ this.resetFormGroupValue(newValue);
3861
+ this.showRelevantFormFields();
3862
+ }
3863
+ });
3864
+ }
3865
+ }
3866
+ ngOnDestroy() {
3867
+ this.ngUnsubscribe.next();
3868
+ this.ngUnsubscribe.complete();
3869
+ }
3870
+ onFieldBlur() {
3871
+ this.onTouched();
3872
+ }
3873
+ writeValue(value) {
3874
+ // Only update the underlying controls when the calculators are ready.
3875
+ const notifyChange = false;
3876
+ // (We still need to save the initial value set by the consumer's form, however.)
3877
+ this.setValue(value, notifyChange);
3878
+ if (this.isReady) {
3879
+ // When the control's value is set to `null`,
3880
+ // set it to the default value.
3881
+ if (!value) {
3882
+ this.onChange(this.defaultValue);
3883
+ }
3884
+ this.resetFormGroupValue();
3885
+ this.showRelevantFormFields();
3886
+ }
3887
+ }
3888
+ validate(control) {
3889
+ if (!this.control) {
3890
+ this.control = control;
3891
+ }
3892
+ if (!this.isReady) {
3893
+ return;
3894
+ }
3895
+ const value = control.value;
3896
+ const idControl = this.calculatorIdControl;
3897
+ const result = this.selectedCalculator.validate(value);
3898
+ let errors;
3899
+ if (result) {
3900
+ errors = {
3901
+ skyDateRange: {
3902
+ calculatorId: idControl.value,
3903
+ errors: result,
3904
+ },
3905
+ };
3906
+ }
3907
+ else {
3908
+ errors = this.startDateControl.errors || this.endDateControl.errors;
3909
+ }
3910
+ if (!errors) {
3911
+ // Clear any errors on the calculator select.
3912
+ // tslint:disable-next-line:no-null-keyword
3913
+ idControl.setErrors(null);
3914
+ return;
3915
+ }
3916
+ idControl.setErrors(errors);
3917
+ idControl.markAsTouched();
3918
+ idControl.markAsDirty();
3919
+ // Need to mark the control as touched for the error messages to appear.
3920
+ this.control.markAsTouched();
3921
+ // Notify the view to display any errors.
3922
+ this.changeDetector.markForCheck();
3923
+ return errors;
3924
+ }
3925
+ registerOnChange(fn) {
3926
+ this.onChange = fn;
3927
+ }
3928
+ registerOnTouched(fn) {
3929
+ this.onTouched = fn;
3930
+ }
3931
+ registerOnValidatorChange(fn) {
3932
+ this.onValidatorChange = fn;
3933
+ }
3934
+ setDisabledState(disabled) {
3935
+ this.disabled = disabled;
3936
+ }
3937
+ setValue(value, notifyChange = true) {
3938
+ const isNewValue = !this.dateRangesEqual(this._value, value);
3939
+ if (isNewValue) {
3940
+ this._value = value;
3941
+ if (notifyChange) {
3942
+ this.onChange(this.value);
3943
+ }
3944
+ }
3945
+ }
3946
+ patchValue(value) {
3947
+ const newValue = Object.assign({}, this.value, value);
3948
+ this.setValue(newValue);
3949
+ }
3950
+ createForm() {
3951
+ this.formGroup = this.formBuilder.group({
3952
+ calculatorId: new FormControl(),
3953
+ startDate: new FormControl(),
3954
+ endDate: new FormControl(),
3955
+ });
3956
+ if (this.disabled) {
3957
+ this.formGroup.disable();
3958
+ }
3959
+ }
3960
+ showRelevantFormFields() {
3961
+ const calculator = this.selectedCalculator;
3962
+ let showEndDatePicker = false;
3963
+ let showStartDatePicker = false;
3964
+ switch (calculator.type) {
3965
+ case SkyDateRangeCalculatorType.Before:
3966
+ showEndDatePicker = true;
3967
+ break;
3968
+ case SkyDateRangeCalculatorType.After:
3969
+ showStartDatePicker = true;
3970
+ break;
3971
+ case SkyDateRangeCalculatorType.Range:
3972
+ showEndDatePicker = true;
3973
+ showStartDatePicker = true;
3974
+ break;
3975
+ default:
3976
+ break;
3977
+ }
3978
+ this.showEndDatePicker = showEndDatePicker;
3979
+ this.showStartDatePicker = showStartDatePicker;
3980
+ this.changeDetector.markForCheck();
3981
+ }
3982
+ resetFormGroupValue(value) {
3983
+ this.formGroup.reset(value || this.value);
3984
+ }
3985
+ addEventListeners() {
3986
+ // Watch for selected calculator change.
3987
+ this.calculatorIdControl.valueChanges
3988
+ .pipe(takeUntil(this.ngUnsubscribe))
3989
+ .subscribe((value) => {
3990
+ if (value !== this.value.calculatorId) {
3991
+ const id = parseInt(value, 10);
3992
+ // if the component is disabled during form creation, null is passed
3993
+ // as the value of the calculator id control
3994
+ // only handle the value changes if the calculator id is a number
3995
+ /* istanbul ignore else */
3996
+ if (!isNaN(id)) {
3997
+ const calculator = this.getCalculatorById(id);
3998
+ const newValue = calculator.getValue();
3999
+ this.setValue(newValue);
4000
+ this.resetFormGroupValue(newValue);
4001
+ this.showRelevantFormFields();
4002
+ }
4003
+ }
4004
+ });
4005
+ // Watch for start date value changes.
4006
+ this.startDateControl.valueChanges
4007
+ .pipe(distinctUntilChanged(), takeUntil(this.ngUnsubscribe))
4008
+ .subscribe((startDate) => {
4009
+ this.patchValue({ startDate });
4010
+ });
4011
+ // Watch for end date value changes.
4012
+ this.endDateControl.valueChanges
4013
+ .pipe(distinctUntilChanged(), takeUntil(this.ngUnsubscribe))
4014
+ .subscribe((endDate) => {
4015
+ this.patchValue({ endDate });
4016
+ });
4017
+ // Detect errors from the date inputs and update ng- classes on picker.
4018
+ combineLatest([
4019
+ this.startDateControl.statusChanges,
4020
+ this.endDateControl.statusChanges,
4021
+ ])
4022
+ .pipe(takeUntil(this.ngUnsubscribe))
4023
+ .subscribe(() => {
4024
+ this.changeDetector.markForCheck();
4025
+ // Wait for initial validation to complete.
4026
+ this.ngZone.onStable.pipe(first()).subscribe(() => {
4027
+ var _a;
4028
+ (_a = this.control) === null || _a === void 0 ? void 0 : _a.updateValueAndValidity({ emitEvent: false });
4029
+ });
4030
+ });
4031
+ }
4032
+ updateCalculators() {
4033
+ return this.dateRangeService
4034
+ .getCalculators(this.calculatorIds)
4035
+ .then((calculators) => {
4036
+ this.calculators = calculators;
4037
+ this.changeDetector.markForCheck();
4038
+ });
4039
+ }
4040
+ getCalculatorById(id) {
4041
+ return this.calculators.find((calculator) => {
4042
+ return calculator.calculatorId === id;
4043
+ });
4044
+ }
4045
+ dateRangesEqual(rangeA, rangeB) {
4046
+ return JSON.stringify(rangeA) === JSON.stringify(rangeB);
4047
+ }
4048
+ }
4049
+ SkyDateRangePickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDateRangePickerComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: SkyDateRangeService }, { token: i2$2.FormBuilder }, { token: i3.SkyAppLocaleProvider }, { token: i1.SkyAppWindowRef }, { token: i0.NgZone }, { token: i3$2.SkyThemeService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
4050
+ SkyDateRangePickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: SkyDateRangePickerComponent, selector: "sky-date-range-picker", inputs: { calculatorIds: "calculatorIds", dateFormat: "dateFormat", disabled: "disabled", label: "label", startDateRequired: "startDateRequired", endDateRequired: "endDateRequired" }, providers: [
4051
+ SKY_DATE_RANGE_PICKER_VALUE_ACCESSOR,
4052
+ SKY_DATE_RANGE_PICKER_VALIDATOR,
4053
+ ], usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"isReady\" class=\"sky-date-range-picker\" [formGroup]=\"formGroup\">\n <div class=\"sky-date-range-picker-form-group\">\n <sky-input-box>\n <label\n class=\"sky-control-label\"\n [attr.for]=\"dateRangePickerId + '-select-calculator'\"\n >\n {{ label || 'skyux_date_range_picker_default_label' | skyLibResources }}\n </label>\n <select\n class=\"sky-form-control\"\n formControlName=\"calculatorId\"\n [attr.id]=\"dateRangePickerId + '-select-calculator'\"\n (blur)=\"onFieldBlur()\"\n >\n <option\n *ngFor=\"let calculator of calculators\"\n [value]=\"calculator.calculatorId\"\n >\n {{ calculator.shortDescription }}\n </option>\n </select>\n </sky-input-box>\n </div>\n\n <div class=\"sky-date-range-picker-form-group\" [hidden]=\"!showStartDatePicker\">\n <sky-input-box>\n <label\n class=\"sky-control-label\"\n [attr.for]=\"dateRangePickerId + '-start-date'\"\n [ngClass]=\"{ 'sky-control-label-required': startDateRequired }\"\n >\n {{ startDateLabelResourceKey | skyLibResources }}\n </label>\n\n <sky-datepicker>\n <input\n formControlName=\"startDate\"\n [attr.aria-label]=\"startDateLabelResourceKey | skyLibResources\"\n [attr.id]=\"dateRangePickerId + '-start-date'\"\n [attr.placeholder]=\"dateFormat\"\n [required]=\"startDateRequired\"\n [dateFormat]=\"dateFormat\"\n (blur)=\"onFieldBlur()\"\n skyDatepickerInput\n />\n </sky-datepicker>\n </sky-input-box>\n </div>\n\n <div class=\"sky-date-range-picker-form-group\" [hidden]=\"!showEndDatePicker\">\n <sky-input-box>\n <label\n class=\"sky-control-label\"\n [attr.for]=\"dateRangePickerId + '-end-date'\"\n [ngClass]=\"{ 'sky-control-label-required': endDateRequired }\"\n >\n {{ endDateLabelResourceKey | skyLibResources }}\n </label>\n\n <sky-datepicker>\n <input\n formControlName=\"endDate\"\n skyDatepickerInput\n [attr.aria-label]=\"endDateLabelResourceKey | skyLibResources\"\n [attr.id]=\"dateRangePickerId + '-end-date'\"\n [attr.placeholder]=\"dateFormat\"\n [dateFormat]=\"dateFormat\"\n [required]=\"endDateRequired\"\n (blur)=\"onFieldBlur()\"\n />\n </sky-datepicker>\n </sky-input-box>\n </div>\n</div>\n", styles: [".sky-date-range-picker{display:flex;margin-left:-5px;margin-right:-5px}.sky-date-range-picker-form-group{padding-left:5px;padding-right:5px}.sky-date-range-picker-form-group:last-child{margin-bottom:0}:host .sky-date-range-picker{flex-direction:column}:host .sky-date-range-picker-form-group{flex-basis:100%}:host-context(.sky-responsive-container-xs) .sky-date-range-picker,:host-context(.sky-responsive-container-sm) .sky-date-range-picker,:host-context(.sky-responsive-container-md) .sky-date-range-picker,:host-context(.sky-responsive-container-lg) .sky-date-range-picker{flex-direction:column}:host-context(.sky-responsive-container-xs) .sky-date-range-picker-form-group,:host-context(.sky-responsive-container-sm) .sky-date-range-picker-form-group,:host-context(.sky-responsive-container-md) .sky-date-range-picker-form-group,:host-context(.sky-responsive-container-lg) .sky-date-range-picker-form-group{flex-basis:100%}@media (min-width: 768px){:host .sky-date-range-picker{flex-direction:initial}:host .sky-date-range-picker-form-group{flex-basis:33.3333333333%;margin-bottom:0}}:host-context(.sky-responsive-container-sm) .sky-date-range-picker,:host-context(.sky-responsive-container-md) .sky-date-range-picker,:host-context(.sky-responsive-container-lg) .sky-date-range-picker{flex-direction:initial}:host-context(.sky-responsive-container-sm) .sky-date-range-picker-form-group,:host-context(.sky-responsive-container-md) .sky-date-range-picker-form-group,:host-context(.sky-responsive-container-lg) .sky-date-range-picker-form-group{flex-basis:33.3333333333%;margin-bottom:0}:host-context(.sky-theme-modern) .sky-date-range-picker-form-group{padding:0;margin:0 0 20px}@media (min-width: 768px){:host-context(.sky-theme-modern) .sky-date-range-picker-form-group{margin:0 20px 0 0}}.sky-theme-modern .sky-date-range-picker-form-group{padding:0;margin:0 0 20px}@media (min-width: 768px){.sky-theme-modern .sky-date-range-picker-form-group{margin:0 20px 0 0}}:host-context(.sky-theme-modern .sky-responsive-container-xs) .sky-date-range-picker-form-group{margin:0 0 20px}:host-context(.sky-theme-modern .sky-responsive-container-sm) .sky-date-range-picker-form-group,:host-context(.sky-theme-modern .sky-responsive-container-md) .sky-date-range-picker-form-group,:host-context(.sky-theme-modern .sky-responsive-container-lg) .sky-date-range-picker-form-group{margin:0 20px 0 0}\n"], components: [{ type: i2$1.λ10, selector: "sky-input-box", inputs: ["hasErrors", "disabled"] }, { type: SkyDatepickerComponent, selector: "sky-datepicker", inputs: ["pickerClass"], outputs: ["calendarDateRangeChange"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i2$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i2$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i2$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i2$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i2$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: SkyDatepickerInputDirective, selector: "[skyDatepickerInput]", inputs: ["dateFormat", "disabled", "maxDate", "minDate", "skyDatepickerInput", "skyDatepickerNoValidate", "startingDay", "strict"] }, { type: i2$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }], pipes: { "skyLibResources": i3.SkyLibResourcesPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
4054
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDateRangePickerComponent, decorators: [{
4055
+ type: Component,
4056
+ args: [{ selector: 'sky-date-range-picker', providers: [
4057
+ SKY_DATE_RANGE_PICKER_VALUE_ACCESSOR,
4058
+ SKY_DATE_RANGE_PICKER_VALIDATOR,
4059
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"isReady\" class=\"sky-date-range-picker\" [formGroup]=\"formGroup\">\n <div class=\"sky-date-range-picker-form-group\">\n <sky-input-box>\n <label\n class=\"sky-control-label\"\n [attr.for]=\"dateRangePickerId + '-select-calculator'\"\n >\n {{ label || 'skyux_date_range_picker_default_label' | skyLibResources }}\n </label>\n <select\n class=\"sky-form-control\"\n formControlName=\"calculatorId\"\n [attr.id]=\"dateRangePickerId + '-select-calculator'\"\n (blur)=\"onFieldBlur()\"\n >\n <option\n *ngFor=\"let calculator of calculators\"\n [value]=\"calculator.calculatorId\"\n >\n {{ calculator.shortDescription }}\n </option>\n </select>\n </sky-input-box>\n </div>\n\n <div class=\"sky-date-range-picker-form-group\" [hidden]=\"!showStartDatePicker\">\n <sky-input-box>\n <label\n class=\"sky-control-label\"\n [attr.for]=\"dateRangePickerId + '-start-date'\"\n [ngClass]=\"{ 'sky-control-label-required': startDateRequired }\"\n >\n {{ startDateLabelResourceKey | skyLibResources }}\n </label>\n\n <sky-datepicker>\n <input\n formControlName=\"startDate\"\n [attr.aria-label]=\"startDateLabelResourceKey | skyLibResources\"\n [attr.id]=\"dateRangePickerId + '-start-date'\"\n [attr.placeholder]=\"dateFormat\"\n [required]=\"startDateRequired\"\n [dateFormat]=\"dateFormat\"\n (blur)=\"onFieldBlur()\"\n skyDatepickerInput\n />\n </sky-datepicker>\n </sky-input-box>\n </div>\n\n <div class=\"sky-date-range-picker-form-group\" [hidden]=\"!showEndDatePicker\">\n <sky-input-box>\n <label\n class=\"sky-control-label\"\n [attr.for]=\"dateRangePickerId + '-end-date'\"\n [ngClass]=\"{ 'sky-control-label-required': endDateRequired }\"\n >\n {{ endDateLabelResourceKey | skyLibResources }}\n </label>\n\n <sky-datepicker>\n <input\n formControlName=\"endDate\"\n skyDatepickerInput\n [attr.aria-label]=\"endDateLabelResourceKey | skyLibResources\"\n [attr.id]=\"dateRangePickerId + '-end-date'\"\n [attr.placeholder]=\"dateFormat\"\n [dateFormat]=\"dateFormat\"\n [required]=\"endDateRequired\"\n (blur)=\"onFieldBlur()\"\n />\n </sky-datepicker>\n </sky-input-box>\n </div>\n</div>\n", styles: [".sky-date-range-picker{display:flex;margin-left:-5px;margin-right:-5px}.sky-date-range-picker-form-group{padding-left:5px;padding-right:5px}.sky-date-range-picker-form-group:last-child{margin-bottom:0}:host .sky-date-range-picker{flex-direction:column}:host .sky-date-range-picker-form-group{flex-basis:100%}:host-context(.sky-responsive-container-xs) .sky-date-range-picker,:host-context(.sky-responsive-container-sm) .sky-date-range-picker,:host-context(.sky-responsive-container-md) .sky-date-range-picker,:host-context(.sky-responsive-container-lg) .sky-date-range-picker{flex-direction:column}:host-context(.sky-responsive-container-xs) .sky-date-range-picker-form-group,:host-context(.sky-responsive-container-sm) .sky-date-range-picker-form-group,:host-context(.sky-responsive-container-md) .sky-date-range-picker-form-group,:host-context(.sky-responsive-container-lg) .sky-date-range-picker-form-group{flex-basis:100%}@media (min-width: 768px){:host .sky-date-range-picker{flex-direction:initial}:host .sky-date-range-picker-form-group{flex-basis:33.3333333333%;margin-bottom:0}}:host-context(.sky-responsive-container-sm) .sky-date-range-picker,:host-context(.sky-responsive-container-md) .sky-date-range-picker,:host-context(.sky-responsive-container-lg) .sky-date-range-picker{flex-direction:initial}:host-context(.sky-responsive-container-sm) .sky-date-range-picker-form-group,:host-context(.sky-responsive-container-md) .sky-date-range-picker-form-group,:host-context(.sky-responsive-container-lg) .sky-date-range-picker-form-group{flex-basis:33.3333333333%;margin-bottom:0}:host-context(.sky-theme-modern) .sky-date-range-picker-form-group{padding:0;margin:0 0 20px}@media (min-width: 768px){:host-context(.sky-theme-modern) .sky-date-range-picker-form-group{margin:0 20px 0 0}}.sky-theme-modern .sky-date-range-picker-form-group{padding:0;margin:0 0 20px}@media (min-width: 768px){.sky-theme-modern .sky-date-range-picker-form-group{margin:0 20px 0 0}}:host-context(.sky-theme-modern .sky-responsive-container-xs) .sky-date-range-picker-form-group{margin:0 0 20px}:host-context(.sky-theme-modern .sky-responsive-container-sm) .sky-date-range-picker-form-group,:host-context(.sky-theme-modern .sky-responsive-container-md) .sky-date-range-picker-form-group,:host-context(.sky-theme-modern .sky-responsive-container-lg) .sky-date-range-picker-form-group{margin:0 20px 0 0}\n"] }]
4060
+ }], ctorParameters: function () {
4061
+ return [{ type: i0.ChangeDetectorRef }, { type: SkyDateRangeService }, { type: i2$2.FormBuilder }, { type: i3.SkyAppLocaleProvider }, { type: i1.SkyAppWindowRef }, { type: i0.NgZone }, { type: i3$2.SkyThemeService, decorators: [{
4062
+ type: Optional
4063
+ }] }];
4064
+ }, propDecorators: { calculatorIds: [{
4065
+ type: Input
4066
+ }], dateFormat: [{
4067
+ type: Input
4068
+ }], disabled: [{
4069
+ type: Input
4070
+ }], label: [{
4071
+ type: Input
4072
+ }], startDateRequired: [{
4073
+ type: Input
4074
+ }], endDateRequired: [{
4075
+ type: Input
4076
+ }] } });
4077
+
4078
+ class SkyDateRangePickerModule {
4079
+ }
4080
+ SkyDateRangePickerModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDateRangePickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
4081
+ SkyDateRangePickerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDateRangePickerModule, declarations: [SkyDateRangePickerComponent], imports: [CommonModule,
4082
+ FormsModule,
4083
+ ReactiveFormsModule,
4084
+ SkyI18nModule,
4085
+ SkyDatepickerModule,
4086
+ SkyDatetimeResourcesModule,
4087
+ SkyInputBoxModule], exports: [SkyDateRangePickerComponent] });
4088
+ SkyDateRangePickerModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDateRangePickerModule, providers: [SkyDateRangeService], imports: [[
4089
+ CommonModule,
4090
+ FormsModule,
4091
+ ReactiveFormsModule,
4092
+ SkyI18nModule,
4093
+ SkyDatepickerModule,
4094
+ SkyDatetimeResourcesModule,
4095
+ SkyInputBoxModule,
4096
+ ]] });
4097
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyDateRangePickerModule, decorators: [{
4098
+ type: NgModule,
4099
+ args: [{
4100
+ declarations: [SkyDateRangePickerComponent],
4101
+ imports: [
4102
+ CommonModule,
4103
+ FormsModule,
4104
+ ReactiveFormsModule,
4105
+ SkyI18nModule,
4106
+ SkyDatepickerModule,
4107
+ SkyDatetimeResourcesModule,
4108
+ SkyInputBoxModule,
4109
+ ],
4110
+ exports: [SkyDateRangePickerComponent],
4111
+ providers: [SkyDateRangeService],
4112
+ }]
4113
+ }] });
4114
+
4115
+ let nextId = 0;
4116
+ /**
4117
+ * Creates a SKY UX-themed replacement for the HTML `input` element with `type="time"`.
4118
+ * The value that users select is driven through the `ngModel` attribute
4119
+ * specified on the `input` element. You must wrap this component around an `input`
4120
+ * with the `skyTimepickerInput` directive.
4121
+ */
4122
+ class SkyTimepickerComponent {
4123
+ constructor(affixService, changeDetector, coreAdapter, overlayService, inputBoxHostService, themeSvc) {
4124
+ this.affixService = affixService;
4125
+ this.changeDetector = changeDetector;
4126
+ this.coreAdapter = coreAdapter;
4127
+ this.overlayService = overlayService;
4128
+ this.inputBoxHostService = inputBoxHostService;
4129
+ /**
4130
+ * Fires when the value in the timepicker input changes.
4131
+ */
4132
+ this.selectedTimeChanged = new EventEmitter();
4133
+ this.is8601 = false;
4134
+ this.timeFormat = 'hh';
4135
+ this.ngUnsubscribe = new Subject();
4136
+ const uniqueId = nextId++;
4137
+ this.timepickerId = `sky-timepicker-${uniqueId}`;
4138
+ this.triggerButtonId = `sky-timepicker-button-${uniqueId}`;
4139
+ // Update icons when theme changes.
4140
+ themeSvc === null || themeSvc === void 0 ? void 0 : themeSvc.settingsChange.pipe(takeUntil(this.ngUnsubscribe)).subscribe(() => {
4141
+ this.changeDetector.markForCheck();
4142
+ });
4143
+ }
4144
+ set disabled(value) {
4145
+ this._disabled = value;
4146
+ this.changeDetector.markForCheck();
4147
+ }
4148
+ get disabled() {
4149
+ return this._disabled;
4150
+ }
4151
+ set selectedHour(setHour) {
4152
+ let hourOffset = 0;
4153
+ if (this.selectedMeridies === 'AM' && setHour === 12) {
4154
+ hourOffset = -12;
4155
+ }
4156
+ if (this.selectedMeridies === 'PM' && setHour !== 12) {
4157
+ hourOffset = 12;
4158
+ }
4159
+ if (this.is8601) {
4160
+ hourOffset = 0;
4161
+ }
4162
+ const hour = moment({ hour: setHour }).add(hourOffset, 'hours').hour();
4163
+ this.activeTime = moment({
4164
+ hour: hour,
4165
+ minute: moment(this.activeTime).get('minute') + 0,
4166
+ }).toDate();
4167
+ this.selectedTimeChanged.emit(this.selectedTime);
4168
+ }
4169
+ get selectedHour() {
4170
+ if (!this.is8601) {
4171
+ /* istanbul ignore next */
4172
+ return parseInt(moment(this.activeTime).format('h'), 0) || 1;
4173
+ }
4174
+ /* istanbul ignore else */
4175
+ if (this.is8601) {
4176
+ return moment(this.activeTime).hour() + 0;
4177
+ }
4178
+ }
4179
+ set selectedMeridies(meridies) {
4180
+ /* istanbul ignore else */
4181
+ if (!this.is8601) {
4182
+ if (meridies.trim() !== this.selectedMeridies) {
4183
+ this.activeTime = moment(this.activeTime).add(12, 'hours').toDate();
4184
+ this.selectedTimeChanged.emit(this.selectedTime);
4185
+ }
4186
+ }
4187
+ }
4188
+ get selectedMeridies() {
4189
+ if (this.activeTime) {
4190
+ return moment(this.activeTime).format('A');
4191
+ }
4192
+ return '';
4193
+ }
4194
+ set selectedMinute(minute) {
4195
+ this.activeTime = moment({
4196
+ hour: moment(this.activeTime).get('hour') + 0,
4197
+ minute: minute,
4198
+ }).toDate();
4199
+ this.selectedTimeChanged.emit(this.selectedTime);
4200
+ }
4201
+ get selectedMinute() {
4202
+ return moment(this.activeTime).minute() + 0;
4203
+ }
4204
+ set selectedTime(newTime) {
4205
+ if (typeof newTime !== 'undefined') {
4206
+ /* sanity check */
4207
+ /* istanbul ignore else */
4208
+ if (newTime.local !== 'Invalid date') {
4209
+ this.activeTime = newTime.iso8601;
4210
+ this.changeDetector.markForCheck();
4211
+ }
4212
+ }
4213
+ }
4214
+ get selectedTime() {
4215
+ const time = {
4216
+ hour: moment(this.activeTime).hour(),
4217
+ minute: moment(this.activeTime).minute(),
4218
+ meridie: moment(this.activeTime).format('A'),
4219
+ timezone: parseInt(moment(this.activeTime).format('Z'), 10),
4220
+ iso8601: this.activeTime,
4221
+ local: moment(this.activeTime).format(this.localeFormat),
4222
+ customFormat: typeof this.returnFormat !== 'undefined'
4223
+ ? this.returnFormat
4224
+ : this.localeFormat,
4225
+ };
4226
+ return time;
4227
+ }
4228
+ set timepickerRef(value) {
4229
+ if (value) {
4230
+ this._timepickerRef = value;
4231
+ // Wait for the timepicker component to render before guaging dimensions.
4232
+ setTimeout(() => {
4233
+ this.destroyAffixer();
4234
+ this.createAffixer();
4235
+ setTimeout(() => {
4236
+ this.coreAdapter.getFocusableChildrenAndApplyFocus(this.timepickerRef, '.sky-timepicker-content', false);
4237
+ this.isVisible = true;
4238
+ this.changeDetector.markForCheck();
4239
+ });
4240
+ });
4241
+ }
4242
+ }
4243
+ get timepickerRef() {
4244
+ return this._timepickerRef;
4245
+ }
4246
+ ngOnInit() {
4247
+ this.setFormat(this.timeFormat);
4248
+ this.addKeydownListner();
4249
+ if (this.inputBoxHostService) {
4250
+ this.inputBoxHostService.populate({
4251
+ inputTemplate: this.inputTemplateRef,
4252
+ buttonsTemplate: this.triggerButtonTemplateRef,
4253
+ });
4254
+ }
4255
+ }
4256
+ ngOnDestroy() {
4257
+ this.ngUnsubscribe.next();
4258
+ this.ngUnsubscribe.complete();
4259
+ this.removePickerEventListeners();
4260
+ this.destroyAffixer();
4261
+ this.destroyOverlay();
4262
+ }
4263
+ setFormat(format) {
4264
+ let h = 12;
4265
+ let m = 12;
4266
+ let minuteMultiplier = 5;
4267
+ let localeFormat = 'h:mm A';
4268
+ if (format === 'hh') {
4269
+ h = 12;
4270
+ m = 12;
4271
+ minuteMultiplier = 5;
4272
+ localeFormat = 'h:mm A';
4273
+ this.is8601 = false;
4274
+ }
4275
+ if (format === 'HH') {
4276
+ h = 24;
4277
+ m = 4;
4278
+ minuteMultiplier = 15;
4279
+ localeFormat = 'HH:mm';
4280
+ this.is8601 = true;
4281
+ }
4282
+ const data = {
4283
+ // Create a sparse array with a length equal to the hour.
4284
+ hours: Array(...Array(h)).map((_, i) => {
4285
+ if (format === 'hh') {
4286
+ return ++i;
4287
+ }
4288
+ /* istanbul ignore else */
4289
+ if (format === 'HH') {
4290
+ return i;
4291
+ }
4292
+ /* istanbul ignore next */
4293
+ /* sanity check */
4294
+ return 0;
4295
+ }),
4296
+ // Create a sparse array with a length equal to the minute.
4297
+ minutes: Array(...Array(m)).map(function (_, i) {
4298
+ return i * minuteMultiplier;
4299
+ }),
4300
+ localeFormat: localeFormat,
4301
+ minuteMultiplier: minuteMultiplier,
4302
+ };
4303
+ this.hours = data.hours;
4304
+ this.minutes = data.minutes;
4305
+ this.localeFormat = data.localeFormat;
4306
+ this.minuteMultiplier = data.minuteMultiplier;
4307
+ }
4308
+ onCloseButtonCick() {
4309
+ this.closePicker();
4310
+ }
4311
+ setTime(event) {
4312
+ /* istanbul ignore else */
4313
+ if (typeof event !== 'undefined') {
4314
+ /* istanbul ignore else */
4315
+ if (event.type === 'click') {
4316
+ event.stopPropagation();
4317
+ if (event.target.name === 'hour') {
4318
+ this.selectedHour = parseInt(event.target.innerHTML, 0);
4319
+ }
4320
+ if (event.target.name === 'minute') {
4321
+ this.selectedMinute = parseInt(event.target.innerHTML, 0);
4322
+ }
4323
+ if (event.target.name === 'meridie') {
4324
+ this.selectedMeridies = event.target.innerHTML;
4325
+ }
4326
+ }
4327
+ }
4328
+ }
4329
+ onTriggerButtonClick() {
4330
+ this.openPicker();
4331
+ }
4332
+ closePicker() {
4333
+ this.destroyAffixer();
4334
+ this.destroyOverlay();
4335
+ this.removePickerEventListeners();
4336
+ this.triggerButtonRef.nativeElement.focus();
4337
+ this.isOpen = false;
4338
+ }
4339
+ openPicker() {
4340
+ this.isVisible = false;
4341
+ this.changeDetector.markForCheck();
4342
+ this.removePickerEventListeners();
4343
+ this.timepickerUnsubscribe = new Subject();
4344
+ this.destroyOverlay();
4345
+ this.createOverlay();
4346
+ this.isOpen = true;
4347
+ this.changeDetector.markForCheck();
4348
+ }
4349
+ createAffixer() {
4350
+ const affixer = this.affixService.createAffixer(this.timepickerRef);
4351
+ // Hide timepicker when trigger button is scrolled off screen.
4352
+ affixer.placementChange
4353
+ .pipe(takeUntil(this.timepickerUnsubscribe))
4354
+ .subscribe((change) => {
4355
+ this.isVisible = change.placement !== null;
4356
+ this.changeDetector.markForCheck();
4357
+ });
4358
+ affixer.affixTo(this.triggerButtonRef.nativeElement, {
4359
+ autoFitContext: SkyAffixAutoFitContext.Viewport,
4360
+ enableAutoFit: true,
4361
+ horizontalAlignment: 'right',
4362
+ isSticky: true,
4363
+ placement: 'below',
4364
+ });
4365
+ this.affixer = affixer;
4366
+ }
4367
+ destroyAffixer() {
4368
+ /*istanbul ignore else*/
4369
+ if (this.affixer) {
4370
+ this.affixer.destroy();
4371
+ this.affixer = undefined;
4372
+ }
4373
+ }
4374
+ createOverlay() {
4375
+ const overlay = this.overlayService.create({
4376
+ enableClose: false,
4377
+ enablePointerEvents: false,
4378
+ });
4379
+ overlay.backdropClick
4380
+ .pipe(takeUntil(this.timepickerUnsubscribe))
4381
+ .subscribe(() => {
4382
+ /* istanbul ignore else */
4383
+ if (this.isOpen) {
4384
+ this.closePicker();
4385
+ }
4386
+ });
4387
+ this.addKeydownListner();
4388
+ overlay.attachTemplate(this.timepickerTemplateRef);
4389
+ this.overlay = overlay;
4390
+ }
4391
+ destroyOverlay() {
4392
+ /*istanbul ignore else*/
4393
+ if (this.overlay) {
4394
+ this.overlayService.close(this.overlay);
4395
+ this.overlay = undefined;
4396
+ }
4397
+ }
4398
+ addKeydownListner() {
4399
+ this.overlayKeydownListner = fromEvent(window.document, 'keydown')
4400
+ .pipe(takeUntil(this.ngUnsubscribe))
4401
+ .subscribe((event) => {
4402
+ var _a;
4403
+ const key = (_a = event.key) === null || _a === void 0 ? void 0 : _a.toLowerCase();
4404
+ /* istanbul ignore else */
4405
+ if (key === 'escape' && this.isOpen) {
4406
+ this.closePicker();
4407
+ }
4408
+ });
4409
+ }
4410
+ removePickerEventListeners() {
4411
+ var _a;
4412
+ /* istanbul ignore else */
4413
+ if (this.timepickerUnsubscribe) {
4414
+ this.timepickerUnsubscribe.next();
4415
+ this.timepickerUnsubscribe.complete();
4416
+ this.timepickerUnsubscribe = undefined;
4417
+ }
4418
+ /* istanbul ignore next */
4419
+ (_a = this.overlayKeydownListner) === null || _a === void 0 ? void 0 : _a.unsubscribe();
4420
+ }
4421
+ }
4422
+ SkyTimepickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyTimepickerComponent, deps: [{ token: i1.SkyAffixService }, { token: i0.ChangeDetectorRef }, { token: i1.SkyCoreAdapterService }, { token: i1.SkyOverlayService }, { token: i2$1.SkyInputBoxHostService, optional: true }, { token: i3$2.SkyThemeService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
4423
+ SkyTimepickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.2.7", type: SkyTimepickerComponent, selector: "sky-timepicker", outputs: { selectedTimeChanged: "selectedTimeChanged" }, viewQueries: [{ propertyName: "timepickerRef", first: true, predicate: ["timepickerRef"], descendants: true, read: ElementRef }, { propertyName: "timepickerTemplateRef", first: true, predicate: ["timepickerTemplateRef"], descendants: true, read: TemplateRef }, { propertyName: "triggerButtonRef", first: true, predicate: ["triggerButtonRef"], descendants: true, read: ElementRef }, { propertyName: "inputTemplateRef", first: true, predicate: ["inputTemplateRef"], descendants: true, read: TemplateRef, static: true }, { propertyName: "triggerButtonTemplateRef", first: true, predicate: ["triggerButtonTemplateRef"], descendants: true, read: TemplateRef, static: true }], ngImport: i0, template: "<div class=\"sky-timepicker\">\n <ng-container *ngIf=\"!inputBoxHostService\">\n <div class=\"sky-input-group\">\n <ng-container *ngTemplateOutlet=\"inputTemplateRef\"></ng-container>\n <ng-container *ngTemplateOutlet=\"triggerButtonTemplateRef\"></ng-container>\n </div>\n </ng-container>\n</div>\n\n<ng-template #inputTemplateRef>\n <ng-content></ng-content>\n</ng-template>\n\n<ng-template #triggerButtonTemplateRef>\n <div class=\"sky-input-group-btn\">\n <button\n aria-haspopup=\"dialog\"\n class=\"sky-btn sky-btn-default sky-input-group-timepicker-btn\"\n type=\"button\"\n [attr.aria-controls]=\"isOpen ? timepickerId : null\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-label]=\"'skyux_timepicker_button_label' | skyLibResources\"\n [attr.id]=\"triggerButtonId\"\n [attr.title]=\"'skyux_timepicker_button_label' | skyLibResources\"\n [disabled]=\"disabled\"\n (click)=\"onTriggerButtonClick()\"\n #triggerButtonRef\n >\n <sky-icon *skyThemeIf=\"'default'\" icon=\"clock-o\" size=\"lg\"></sky-icon>\n <sky-icon\n *skyThemeIf=\"'modern'\"\n icon=\"clock\"\n size=\"lg\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </div>\n</ng-template>\n\n<ng-template #timepickerTemplateRef>\n <div\n class=\"sky-timepicker-container sky-shadow sky-box sky-elevation-4\"\n role=\"dialog\"\n [attr.aria-labelledby]=\"triggerButtonId\"\n [attr.id]=\"timepickerId\"\n [class.sky-timepicker-hidden]=\"!isVisible\"\n #timepickerRef\n >\n <div class=\"sky-timepicker-content\">\n <section\n class=\"sky-timepicker-column\"\n [ngClass]=\"{ 'sky-timepicker-24hour': is8601 }\"\n >\n <ol>\n <li *ngFor=\"let hour of hours\">\n <button\n name=\"hour\"\n type=\"button\"\n [ngClass]=\"{ 'sky-btn-active': selectedHour === hour }\"\n (click)=\"setTime($event)\"\n >\n {{ hour }}\n </button>\n </li>\n </ol>\n </section>\n <section class=\"sky-timepicker-column\">\n <ol>\n <li *ngFor=\"let minute of minutes\">\n <button\n name=\"minute\"\n type=\"button\"\n [ngClass]=\"{ 'sky-btn-active': selectedMinute === minute }\"\n (click)=\"setTime($event)\"\n >\n {{ '00'.substring(0, 2 - minute.toString().length) + minute }}\n </button>\n </li>\n </ol>\n </section>\n <section *ngIf=\"!is8601\" class=\"sky-timepicker-column\">\n <ol>\n <li>\n <button\n name=\"meridie\"\n type=\"button\"\n [ngClass]=\"{ 'sky-btn-active': selectedMeridies === 'AM' }\"\n (click)=\"setTime($event)\"\n >\n AM\n </button>\n </li>\n <li>\n <button\n name=\"meridie\"\n type=\"button\"\n [ngClass]=\"{ 'sky-btn-active': selectedMeridies === 'PM' }\"\n (click)=\"setTime($event)\"\n >\n PM\n </button>\n </li>\n </ol>\n </section>\n </div>\n <div class=\"sky-timepicker-footer\">\n <section class=\"sky-timepicker-column\">\n <button\n class=\"sky-btn sky-btn-primary\"\n type=\"button\"\n (click)=\"onCloseButtonCick()\"\n >\n {{ 'skyux_timepicker_close' | skyLibResources }}\n </button>\n </section>\n </div>\n </div>\n</ng-template>\n", styles: [".sky-timepicker-container{position:fixed;font-size:15px;padding:5px;background-color:#eeeeef;border-radius:5px}.sky-timepicker-container :last-child ol{display:flex;flex-direction:column;height:100%}.sky-timepicker-container :last-child ol li{border-bottom:1px solid #e2e3e4;flex:1}.sky-timepicker-column{margin:5px}.sky-timepicker-column ol{border-top:1px solid #e2e3e4;border-right:1px solid #e2e3e4;border-bottom:1px solid #e2e3e4;border-left:1px solid #e2e3e4;column-gap:1px;columns:2;list-style-type:none;margin:0;padding:0}.sky-timepicker-column ol li{text-align:center;cursor:pointer;margin:0}.sky-timepicker-column ol li button{cursor:pointer}.sky-timepicker-column ol li button:focus{outline:thin dotted;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.sky-timepicker-column ol li button:hover{background-color:#eeeeef}.sky-timepicker-column ol li button:active{background-color:#e2e3e4}.sky-timepicker-column ol li button.sky-btn-active:hover{background-color:#c1e8fb}.sky-timepicker-column ol .sky-btn-active{background-color:#c1e8fb;box-shadow:inset 0 0 0 2px #00b4f1;border-radius:3px}.sky-timepicker-column.sky-timepicker-24hour ol{columns:4}.sky-timepicker-column.sky-timepicker-24hour ol li{border-bottom-width:0}.sky-timepicker-content{display:flex}.sky-timepicker-content button{background-color:#fff;border-width:0;padding:5px 15px;width:100%;height:100%}.sky-timepicker-footer{margin:0;padding:0 5px}.sky-timepicker-footer .sky-timepicker-column{margin-left:0;margin-right:0;width:100%}.sky-timepicker-hidden{visibility:hidden}.sky-timepicker-clock-icon-modern,.sky-theme-modern .sky-timepicker-clock-icon-default{display:none}.sky-theme-modern .sky-timepicker-clock-icon-modern{display:inline}.sky-theme-modern .sky-timepicker-container{background-color:#fff;border:solid 1px #cdcfd2;border-radius:6px;font-size:16px}.sky-theme-modern .sky-timepicker-container:focus-within{border:solid 2px #1870B8;padding:4px}.sky-theme-modern .sky-timepicker-container:last-child ol li{border-bottom:none}.sky-theme-modern .sky-timepicker-container .sky-timepicker-column ol .sky-btn-default{border-width:1px;border-color:transparent;padding:4px 6px;outline:none}.sky-theme-modern .sky-timepicker-container .sky-timepicker-column ol button:hover:not(.sky-btn-active){background-color:transparent}.sky-theme-modern .sky-timepicker-container .sky-timepicker-column ol .sky-btn-active,.sky-theme-modern .sky-timepicker-container .sky-timepicker-column ol button:hover{box-shadow:inset 0 0 0 1px #00b4f1;border-radius:6px}.sky-theme-modern .sky-timepicker-container .sky-timepicker-column ol button:active,.sky-theme-modern .sky-timepicker-container .sky-timepicker-column ol button:focus{outline:none;border-radius:6px;box-shadow:inset 0 0 0 2px #1870b8}.sky-theme-modern.sky-theme-mode-dark .sky-timepicker-container{color:#fbfcfe}.sky-theme-modern.sky-theme-mode-dark .sky-timepicker-container:not(:focus-within){border-color:#686c73}.sky-theme-modern.sky-theme-mode-dark .sky-timepicker-column ol{border-color:#686c73}.sky-theme-modern.sky-theme-mode-dark .sky-timepicker-column ol button{background-color:transparent;color:#fbfcfe}.sky-theme-modern.sky-theme-mode-dark .sky-timepicker-column ol .sky-btn-active{background-color:#009cd1}\n"], components: [{ type: i2.λ4, selector: "sky-icon", inputs: ["icon", "iconType", "size", "fixedWidth", "variant"] }], directives: [{ type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i5.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i3$2.λ3, selector: "[skyThemeIf]", inputs: ["skyThemeIf"] }, { type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], pipes: { "skyLibResources": i3.SkyLibResourcesPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
4424
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyTimepickerComponent, decorators: [{
4425
+ type: Component,
4426
+ args: [{ selector: 'sky-timepicker', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"sky-timepicker\">\n <ng-container *ngIf=\"!inputBoxHostService\">\n <div class=\"sky-input-group\">\n <ng-container *ngTemplateOutlet=\"inputTemplateRef\"></ng-container>\n <ng-container *ngTemplateOutlet=\"triggerButtonTemplateRef\"></ng-container>\n </div>\n </ng-container>\n</div>\n\n<ng-template #inputTemplateRef>\n <ng-content></ng-content>\n</ng-template>\n\n<ng-template #triggerButtonTemplateRef>\n <div class=\"sky-input-group-btn\">\n <button\n aria-haspopup=\"dialog\"\n class=\"sky-btn sky-btn-default sky-input-group-timepicker-btn\"\n type=\"button\"\n [attr.aria-controls]=\"isOpen ? timepickerId : null\"\n [attr.aria-expanded]=\"isOpen\"\n [attr.aria-label]=\"'skyux_timepicker_button_label' | skyLibResources\"\n [attr.id]=\"triggerButtonId\"\n [attr.title]=\"'skyux_timepicker_button_label' | skyLibResources\"\n [disabled]=\"disabled\"\n (click)=\"onTriggerButtonClick()\"\n #triggerButtonRef\n >\n <sky-icon *skyThemeIf=\"'default'\" icon=\"clock-o\" size=\"lg\"></sky-icon>\n <sky-icon\n *skyThemeIf=\"'modern'\"\n icon=\"clock\"\n size=\"lg\"\n iconType=\"skyux\"\n ></sky-icon>\n </button>\n </div>\n</ng-template>\n\n<ng-template #timepickerTemplateRef>\n <div\n class=\"sky-timepicker-container sky-shadow sky-box sky-elevation-4\"\n role=\"dialog\"\n [attr.aria-labelledby]=\"triggerButtonId\"\n [attr.id]=\"timepickerId\"\n [class.sky-timepicker-hidden]=\"!isVisible\"\n #timepickerRef\n >\n <div class=\"sky-timepicker-content\">\n <section\n class=\"sky-timepicker-column\"\n [ngClass]=\"{ 'sky-timepicker-24hour': is8601 }\"\n >\n <ol>\n <li *ngFor=\"let hour of hours\">\n <button\n name=\"hour\"\n type=\"button\"\n [ngClass]=\"{ 'sky-btn-active': selectedHour === hour }\"\n (click)=\"setTime($event)\"\n >\n {{ hour }}\n </button>\n </li>\n </ol>\n </section>\n <section class=\"sky-timepicker-column\">\n <ol>\n <li *ngFor=\"let minute of minutes\">\n <button\n name=\"minute\"\n type=\"button\"\n [ngClass]=\"{ 'sky-btn-active': selectedMinute === minute }\"\n (click)=\"setTime($event)\"\n >\n {{ '00'.substring(0, 2 - minute.toString().length) + minute }}\n </button>\n </li>\n </ol>\n </section>\n <section *ngIf=\"!is8601\" class=\"sky-timepicker-column\">\n <ol>\n <li>\n <button\n name=\"meridie\"\n type=\"button\"\n [ngClass]=\"{ 'sky-btn-active': selectedMeridies === 'AM' }\"\n (click)=\"setTime($event)\"\n >\n AM\n </button>\n </li>\n <li>\n <button\n name=\"meridie\"\n type=\"button\"\n [ngClass]=\"{ 'sky-btn-active': selectedMeridies === 'PM' }\"\n (click)=\"setTime($event)\"\n >\n PM\n </button>\n </li>\n </ol>\n </section>\n </div>\n <div class=\"sky-timepicker-footer\">\n <section class=\"sky-timepicker-column\">\n <button\n class=\"sky-btn sky-btn-primary\"\n type=\"button\"\n (click)=\"onCloseButtonCick()\"\n >\n {{ 'skyux_timepicker_close' | skyLibResources }}\n </button>\n </section>\n </div>\n </div>\n</ng-template>\n", styles: [".sky-timepicker-container{position:fixed;font-size:15px;padding:5px;background-color:#eeeeef;border-radius:5px}.sky-timepicker-container :last-child ol{display:flex;flex-direction:column;height:100%}.sky-timepicker-container :last-child ol li{border-bottom:1px solid #e2e3e4;flex:1}.sky-timepicker-column{margin:5px}.sky-timepicker-column ol{border-top:1px solid #e2e3e4;border-right:1px solid #e2e3e4;border-bottom:1px solid #e2e3e4;border-left:1px solid #e2e3e4;column-gap:1px;columns:2;list-style-type:none;margin:0;padding:0}.sky-timepicker-column ol li{text-align:center;cursor:pointer;margin:0}.sky-timepicker-column ol li button{cursor:pointer}.sky-timepicker-column ol li button:focus{outline:thin dotted;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px}.sky-timepicker-column ol li button:hover{background-color:#eeeeef}.sky-timepicker-column ol li button:active{background-color:#e2e3e4}.sky-timepicker-column ol li button.sky-btn-active:hover{background-color:#c1e8fb}.sky-timepicker-column ol .sky-btn-active{background-color:#c1e8fb;box-shadow:inset 0 0 0 2px #00b4f1;border-radius:3px}.sky-timepicker-column.sky-timepicker-24hour ol{columns:4}.sky-timepicker-column.sky-timepicker-24hour ol li{border-bottom-width:0}.sky-timepicker-content{display:flex}.sky-timepicker-content button{background-color:#fff;border-width:0;padding:5px 15px;width:100%;height:100%}.sky-timepicker-footer{margin:0;padding:0 5px}.sky-timepicker-footer .sky-timepicker-column{margin-left:0;margin-right:0;width:100%}.sky-timepicker-hidden{visibility:hidden}.sky-timepicker-clock-icon-modern,.sky-theme-modern .sky-timepicker-clock-icon-default{display:none}.sky-theme-modern .sky-timepicker-clock-icon-modern{display:inline}.sky-theme-modern .sky-timepicker-container{background-color:#fff;border:solid 1px #cdcfd2;border-radius:6px;font-size:16px}.sky-theme-modern .sky-timepicker-container:focus-within{border:solid 2px #1870B8;padding:4px}.sky-theme-modern .sky-timepicker-container:last-child ol li{border-bottom:none}.sky-theme-modern .sky-timepicker-container .sky-timepicker-column ol .sky-btn-default{border-width:1px;border-color:transparent;padding:4px 6px;outline:none}.sky-theme-modern .sky-timepicker-container .sky-timepicker-column ol button:hover:not(.sky-btn-active){background-color:transparent}.sky-theme-modern .sky-timepicker-container .sky-timepicker-column ol .sky-btn-active,.sky-theme-modern .sky-timepicker-container .sky-timepicker-column ol button:hover{box-shadow:inset 0 0 0 1px #00b4f1;border-radius:6px}.sky-theme-modern .sky-timepicker-container .sky-timepicker-column ol button:active,.sky-theme-modern .sky-timepicker-container .sky-timepicker-column ol button:focus{outline:none;border-radius:6px;box-shadow:inset 0 0 0 2px #1870b8}.sky-theme-modern.sky-theme-mode-dark .sky-timepicker-container{color:#fbfcfe}.sky-theme-modern.sky-theme-mode-dark .sky-timepicker-container:not(:focus-within){border-color:#686c73}.sky-theme-modern.sky-theme-mode-dark .sky-timepicker-column ol{border-color:#686c73}.sky-theme-modern.sky-theme-mode-dark .sky-timepicker-column ol button{background-color:transparent;color:#fbfcfe}.sky-theme-modern.sky-theme-mode-dark .sky-timepicker-column ol .sky-btn-active{background-color:#009cd1}\n"] }]
4427
+ }], ctorParameters: function () {
4428
+ return [{ type: i1.SkyAffixService }, { type: i0.ChangeDetectorRef }, { type: i1.SkyCoreAdapterService }, { type: i1.SkyOverlayService }, { type: i2$1.SkyInputBoxHostService, decorators: [{
4429
+ type: Optional
4430
+ }] }, { type: i3$2.SkyThemeService, decorators: [{
4431
+ type: Optional
4432
+ }] }];
4433
+ }, propDecorators: { selectedTimeChanged: [{
4434
+ type: Output
4435
+ }], timepickerRef: [{
4436
+ type: ViewChild,
4437
+ args: ['timepickerRef', {
4438
+ read: ElementRef,
4439
+ }]
4440
+ }], timepickerTemplateRef: [{
4441
+ type: ViewChild,
4442
+ args: ['timepickerTemplateRef', {
4443
+ read: TemplateRef,
4444
+ }]
4445
+ }], triggerButtonRef: [{
4446
+ type: ViewChild,
4447
+ args: ['triggerButtonRef', {
4448
+ read: ElementRef,
4449
+ }]
4450
+ }], inputTemplateRef: [{
4451
+ type: ViewChild,
4452
+ args: ['inputTemplateRef', {
4453
+ read: TemplateRef,
4454
+ static: true,
4455
+ }]
4456
+ }], triggerButtonTemplateRef: [{
4457
+ type: ViewChild,
4458
+ args: ['triggerButtonTemplateRef', {
4459
+ read: TemplateRef,
4460
+ static: true,
4461
+ }]
4462
+ }] } });
4463
+
4464
+ // tslint:disable:no-forward-ref no-use-before-declare
4465
+ const SKY_TIMEPICKER_VALUE_ACCESSOR = {
4466
+ provide: NG_VALUE_ACCESSOR,
4467
+ useExisting: forwardRef(() => SkyTimepickerInputDirective),
4468
+ multi: true,
4469
+ };
4470
+ const SKY_TIMEPICKER_VALIDATOR = {
4471
+ provide: NG_VALIDATORS,
4472
+ useExisting: forwardRef(() => SkyTimepickerInputDirective),
4473
+ multi: true,
4474
+ };
4475
+ // tslint:enable
4476
+ class SkyTimepickerInputDirective {
4477
+ constructor(renderer, elRef, resourcesService, changeDetector) {
4478
+ this.renderer = renderer;
4479
+ this.elRef = elRef;
4480
+ this.resourcesService = resourcesService;
4481
+ this.changeDetector = changeDetector;
4482
+ this._timeFormat = 'hh';
4483
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
4484
+ this._onChange = (_) => { };
4485
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
4486
+ this._onTouched = () => { };
4487
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
4488
+ this._validatorChange = () => { };
4489
+ }
4490
+ /**
4491
+ * Creates the timepicker input field and picker. Place this attribute on an `input` element,
4492
+ * and wrap the input in a `sky-timepicker` component.
4493
+ * This attribute must be set to the instance of the `sky-timepicker`.
4494
+ * @required
4495
+ */
4496
+ get skyTimepickerInput() {
4497
+ return this._skyTimepickerInput;
4498
+ }
4499
+ set skyTimepickerInput(value) {
4500
+ this._skyTimepickerInput = value;
4501
+ this.updateTimepickerInput();
4502
+ }
4503
+ /**
4504
+ * Specifies the 12-hour `hh` or 24-hour `HH` time format for the input.
4505
+ * @default "hh"
4506
+ */
4507
+ set timeFormat(value) {
4508
+ this._timeFormat = value;
4509
+ }
4510
+ get timeFormat() {
4511
+ return this._timeFormat || 'hh';
4512
+ }
4513
+ /**
4514
+ * Indicates whether to disable the timepicker.
4515
+ * @default false
4516
+ */
4517
+ get disabled() {
4518
+ return this._disabled || false;
4519
+ }
4520
+ set disabled(value) {
4521
+ this._disabled = value;
4522
+ this.updateTimepickerInput();
4523
+ this.renderer.setProperty(this.elRef.nativeElement, 'disabled', value);
4524
+ }
4525
+ get modelValue() {
4526
+ return this._modelValue;
4527
+ }
4528
+ set modelValue(value) {
4529
+ if (value !== this._modelValue) {
4530
+ this._modelValue = value;
4531
+ this.updateTimepickerInput();
4532
+ this.setInputValue(value);
4533
+ this._validatorChange();
4534
+ this._onChange(value);
4535
+ }
4536
+ }
4537
+ ngOnInit() {
4538
+ this.renderer.addClass(this.elRef.nativeElement, 'sky-form-control');
4539
+ this.pickerChangedSubscription =
4540
+ this.skyTimepickerInput.selectedTimeChanged.subscribe((newTime) => {
4541
+ this.writeValue(newTime);
4542
+ this._onTouched();
4543
+ });
4544
+ /* istanbul ignore else */
4545
+ if (!this.elRef.nativeElement.getAttribute('aria-label')) {
4546
+ this.resourcesService
4547
+ .getString('skyux_timepicker_input_default_label')
4548
+ .subscribe((value) => {
4549
+ this.renderer.setAttribute(this.elRef.nativeElement, 'aria-label', value);
4550
+ });
4551
+ }
4552
+ }
4553
+ ngAfterContentInit() {
4554
+ // Watch for the control to be added and initialize the value immediately.
4555
+ /* istanbul ignore else */
4556
+ if (this.control && this.control.parent) {
4557
+ this.control.setValue(this.modelValue, {
4558
+ emitEvent: false,
4559
+ });
4560
+ this.changeDetector.markForCheck();
4561
+ }
4562
+ }
4563
+ ngOnDestroy() {
4564
+ this.pickerChangedSubscription.unsubscribe();
4565
+ }
4566
+ ngOnChanges() {
4567
+ this.skyTimepickerInput.setFormat(this.timeFormat);
4568
+ this.skyTimepickerInput.returnFormat = this.returnFormat;
4569
+ }
4570
+ onChange(event) {
4571
+ this.writeValue(event.target.value);
4572
+ }
4573
+ /* istanbul ignore next */
4574
+ onBlur() {
4575
+ this._onTouched();
4576
+ }
4577
+ registerOnChange(fn) {
4578
+ this._onChange = fn;
4579
+ }
4580
+ registerOnTouched(fn) {
4581
+ this._onTouched = fn;
4582
+ }
4583
+ registerOnValidatorChange(fn) {
4584
+ this._validatorChange = fn;
4585
+ }
4586
+ setDisabledState(isDisabled) {
4587
+ this.disabled = isDisabled;
4588
+ }
4589
+ writeValue(value) {
4590
+ this.modelValue = this.formatter(value);
4591
+ }
4592
+ validate(control) {
4593
+ if (!this.control) {
4594
+ this.control = control;
4595
+ }
4596
+ const value = control.value;
4597
+ if (!value) {
4598
+ return undefined;
4599
+ }
4600
+ /* istanbul ignore next */
4601
+ if (value.local === 'Invalid date') {
4602
+ return {
4603
+ skyTime: {
4604
+ invalid: control.value,
4605
+ },
4606
+ };
4607
+ }
4608
+ return undefined;
4609
+ }
4610
+ setInputValue(value) {
4611
+ let formattedValue = '';
4612
+ if (value) {
4613
+ const output = moment(value).format(value.customFormat);
4614
+ /* istanbul ignore else */
4615
+ if (output !== 'Invalid date') {
4616
+ formattedValue = output;
4617
+ }
4618
+ }
4619
+ this.renderer.setProperty(this.elRef.nativeElement, 'value', formattedValue);
4620
+ }
4621
+ formatter(time) {
4622
+ if (time && typeof time !== 'string' && 'local' in time) {
4623
+ return time;
4624
+ }
4625
+ if (typeof time === 'string') {
4626
+ if (time.length === 0) {
4627
+ return '';
4628
+ }
4629
+ let currentFormat;
4630
+ if (this.timeFormat === 'hh') {
4631
+ currentFormat = 'h:mm A';
4632
+ }
4633
+ if (this.timeFormat === 'HH') {
4634
+ currentFormat = 'H:mm';
4635
+ }
4636
+ if (typeof this.returnFormat === 'undefined') {
4637
+ this.returnFormat = currentFormat;
4638
+ }
4639
+ const formatTime = {
4640
+ hour: moment(time, currentFormat).hour(),
4641
+ minute: moment(time, currentFormat).minute(),
4642
+ meridie: moment(time, currentFormat).format('A'),
4643
+ timezone: parseInt(moment(time, currentFormat).format('Z'), 10),
4644
+ iso8601: moment(time, currentFormat).toDate(),
4645
+ local: moment(time, currentFormat).format(currentFormat),
4646
+ customFormat: this.returnFormat,
4647
+ };
4648
+ return formatTime;
4649
+ }
4650
+ }
4651
+ updateTimepickerInput() {
4652
+ if (this.skyTimepickerInput) {
4653
+ this.skyTimepickerInput.disabled = this.disabled;
4654
+ /* istanbul ignore else */
4655
+ if (this.skyTimepickerInput.selectedTime !== this.modelValue) {
4656
+ this.skyTimepickerInput.selectedTime = this.modelValue;
4657
+ }
4658
+ }
4659
+ }
4660
+ }
4661
+ SkyTimepickerInputDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyTimepickerInputDirective, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }, { token: i3.SkyLibResourcesService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive });
4662
+ SkyTimepickerInputDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.2.7", type: SkyTimepickerInputDirective, selector: "[skyTimepickerInput]", inputs: { skyTimepickerInput: "skyTimepickerInput", timeFormat: "timeFormat", returnFormat: "returnFormat", disabled: "disabled" }, host: { listeners: { "change": "onChange($event)", "blur": "onBlur()" } }, providers: [SKY_TIMEPICKER_VALUE_ACCESSOR, SKY_TIMEPICKER_VALIDATOR], usesOnChanges: true, ngImport: i0 });
4663
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyTimepickerInputDirective, decorators: [{
4664
+ type: Directive,
4665
+ args: [{
4666
+ selector: '[skyTimepickerInput]',
4667
+ providers: [SKY_TIMEPICKER_VALUE_ACCESSOR, SKY_TIMEPICKER_VALIDATOR],
4668
+ }]
4669
+ }], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.ElementRef }, { type: i3.SkyLibResourcesService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { skyTimepickerInput: [{
4670
+ type: Input
4671
+ }], timeFormat: [{
4672
+ type: Input
4673
+ }], returnFormat: [{
4674
+ type: Input
4675
+ }], disabled: [{
4676
+ type: Input
4677
+ }], onChange: [{
4678
+ type: HostListener,
4679
+ args: ['change', ['$event']]
4680
+ }], onBlur: [{
4681
+ type: HostListener,
4682
+ args: ['blur']
4683
+ }] } });
4684
+
4685
+ class SkyTimepickerModule {
4686
+ }
4687
+ SkyTimepickerModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyTimepickerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
4688
+ SkyTimepickerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyTimepickerModule, declarations: [SkyTimepickerInputDirective, SkyTimepickerComponent], imports: [CommonModule,
4689
+ SkyI18nModule,
4690
+ SkyIconModule,
4691
+ SkyDatetimeResourcesModule,
4692
+ SkyAffixModule,
4693
+ SkyOverlayModule,
4694
+ SkyThemeModule], exports: [SkyTimepickerInputDirective, SkyTimepickerComponent] });
4695
+ SkyTimepickerModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyTimepickerModule, imports: [[
4696
+ CommonModule,
4697
+ SkyI18nModule,
4698
+ SkyIconModule,
4699
+ SkyDatetimeResourcesModule,
4700
+ SkyAffixModule,
4701
+ SkyOverlayModule,
4702
+ SkyThemeModule,
4703
+ ]] });
4704
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.7", ngImport: i0, type: SkyTimepickerModule, decorators: [{
4705
+ type: NgModule,
4706
+ args: [{
4707
+ declarations: [SkyTimepickerInputDirective, SkyTimepickerComponent],
4708
+ imports: [
4709
+ CommonModule,
4710
+ SkyI18nModule,
4711
+ SkyIconModule,
4712
+ SkyDatetimeResourcesModule,
4713
+ SkyAffixModule,
4714
+ SkyOverlayModule,
4715
+ SkyThemeModule,
4716
+ ],
4717
+ exports: [SkyTimepickerInputDirective, SkyTimepickerComponent],
4718
+ }]
4719
+ }] });
4720
+
4721
+ /**
4722
+ * Generated bundle index. Do not edit.
4723
+ */
4724
+
4725
+ export { SkyDatePipe, SkyDatePipeModule, SkyDateRangeCalculator, SkyDateRangeCalculatorId, SkyDateRangeCalculatorType, SkyDateRangePickerModule, SkyDateRangeService, SkyDatepickerConfigService, SkyDatepickerModule, SkyFuzzyDatePipe, SkyFuzzyDateService, SkyTimepickerModule, SkyDatepickerCalendarComponent as λ1, SkyDatepickerComponent as λ2, SkyDatepickerInputDirective as λ3, SkyFuzzyDatepickerInputDirective as λ4, SkyDateRangePickerComponent as λ5, SkyTimepickerComponent as λ6, SkyTimepickerInputDirective as λ7 };
4726
+ //# sourceMappingURL=skyux-datetime.mjs.map