@cdevhub/ngx-tw 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +134 -0
  3. package/fesm2022/cdevhub-ngx-tw-accordion.mjs +108 -0
  4. package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -0
  5. package/fesm2022/cdevhub-ngx-tw-alert.mjs +240 -0
  6. package/fesm2022/cdevhub-ngx-tw-alert.mjs.map +1 -0
  7. package/fesm2022/cdevhub-ngx-tw-avatar.mjs +287 -0
  8. package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -0
  9. package/fesm2022/cdevhub-ngx-tw-badge.mjs +332 -0
  10. package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -0
  11. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +452 -0
  12. package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -0
  13. package/fesm2022/cdevhub-ngx-tw-button.mjs +227 -0
  14. package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -0
  15. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +417 -0
  16. package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -0
  17. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +232 -0
  18. package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -0
  19. package/fesm2022/cdevhub-ngx-tw-calendar.mjs +4482 -0
  20. package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -0
  21. package/fesm2022/cdevhub-ngx-tw-card.mjs +157 -0
  22. package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -0
  23. package/fesm2022/cdevhub-ngx-tw-carousel.mjs +1454 -0
  24. package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -0
  25. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +593 -0
  26. package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -0
  27. package/fesm2022/cdevhub-ngx-tw-code-block.mjs +228 -0
  28. package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -0
  29. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +510 -0
  30. package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -0
  31. package/fesm2022/cdevhub-ngx-tw-combobox.mjs +1721 -0
  32. package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -0
  33. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +721 -0
  34. package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -0
  35. package/fesm2022/cdevhub-ngx-tw-core.mjs +861 -0
  36. package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -0
  37. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +1558 -0
  38. package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -0
  39. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +1833 -0
  40. package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -0
  41. package/fesm2022/cdevhub-ngx-tw-dialog.mjs +693 -0
  42. package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -0
  43. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +331 -0
  44. package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -0
  45. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +289 -0
  46. package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -0
  47. package/fesm2022/cdevhub-ngx-tw-form-field.mjs +572 -0
  48. package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -0
  49. package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs +36 -0
  50. package/fesm2022/cdevhub-ngx-tw-icon-lucide.mjs.map +1 -0
  51. package/fesm2022/cdevhub-ngx-tw-icon.mjs +278 -0
  52. package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -0
  53. package/fesm2022/cdevhub-ngx-tw-input.mjs +355 -0
  54. package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -0
  55. package/fesm2022/cdevhub-ngx-tw-item.mjs +241 -0
  56. package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -0
  57. package/fesm2022/cdevhub-ngx-tw-menu.mjs +433 -0
  58. package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -0
  59. package/fesm2022/cdevhub-ngx-tw-paginator.mjs +691 -0
  60. package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -0
  61. package/fesm2022/cdevhub-ngx-tw-popover.mjs +678 -0
  62. package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -0
  63. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +335 -0
  64. package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -0
  65. package/fesm2022/cdevhub-ngx-tw-radio.mjs +708 -0
  66. package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -0
  67. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +319 -0
  68. package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -0
  69. package/fesm2022/cdevhub-ngx-tw-select.mjs +1722 -0
  70. package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -0
  71. package/fesm2022/cdevhub-ngx-tw-separator.mjs +115 -0
  72. package/fesm2022/cdevhub-ngx-tw-separator.mjs.map +1 -0
  73. package/fesm2022/cdevhub-ngx-tw-sheet.mjs +768 -0
  74. package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -0
  75. package/fesm2022/cdevhub-ngx-tw-skeleton.mjs +149 -0
  76. package/fesm2022/cdevhub-ngx-tw-skeleton.mjs.map +1 -0
  77. package/fesm2022/cdevhub-ngx-tw-slider.mjs +1147 -0
  78. package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -0
  79. package/fesm2022/cdevhub-ngx-tw-sort.mjs +346 -0
  80. package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -0
  81. package/fesm2022/cdevhub-ngx-tw-spinner.mjs +186 -0
  82. package/fesm2022/cdevhub-ngx-tw-spinner.mjs.map +1 -0
  83. package/fesm2022/cdevhub-ngx-tw-split.mjs +1082 -0
  84. package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -0
  85. package/fesm2022/cdevhub-ngx-tw-stat.mjs +579 -0
  86. package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -0
  87. package/fesm2022/cdevhub-ngx-tw-stepper.mjs +443 -0
  88. package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -0
  89. package/fesm2022/cdevhub-ngx-tw-switch.mjs +391 -0
  90. package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -0
  91. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +315 -0
  92. package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -0
  93. package/fesm2022/cdevhub-ngx-tw-table.mjs +994 -0
  94. package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -0
  95. package/fesm2022/cdevhub-ngx-tw-tabs.mjs +508 -0
  96. package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -0
  97. package/fesm2022/cdevhub-ngx-tw-textarea.mjs +147 -0
  98. package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -0
  99. package/fesm2022/cdevhub-ngx-tw-theme.mjs +178 -0
  100. package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -0
  101. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +1344 -0
  102. package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -0
  103. package/fesm2022/cdevhub-ngx-tw-timeline.mjs +1136 -0
  104. package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -0
  105. package/fesm2022/cdevhub-ngx-tw-toast.mjs +1311 -0
  106. package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -0
  107. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +533 -0
  108. package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -0
  109. package/fesm2022/cdevhub-ngx-tw.mjs +61 -0
  110. package/fesm2022/cdevhub-ngx-tw.mjs.map +1 -0
  111. package/package.json +265 -0
  112. package/theme/_base.css +394 -0
  113. package/theme/_dark.css +510 -0
  114. package/theme/_high-contrast.css +290 -0
  115. package/theme/_semantic.css +317 -0
  116. package/theme/_typography.css +9 -0
  117. package/theme/index.css +54 -0
  118. package/types/cdevhub-ngx-tw-accordion.d.ts +48 -0
  119. package/types/cdevhub-ngx-tw-alert.d.ts +67 -0
  120. package/types/cdevhub-ngx-tw-avatar.d.ts +79 -0
  121. package/types/cdevhub-ngx-tw-badge.d.ts +94 -0
  122. package/types/cdevhub-ngx-tw-breadcrumbs.d.ts +227 -0
  123. package/types/cdevhub-ngx-tw-button.d.ts +74 -0
  124. package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +200 -0
  125. package/types/cdevhub-ngx-tw-calendar-testing.d.ts +113 -0
  126. package/types/cdevhub-ngx-tw-calendar.d.ts +1704 -0
  127. package/types/cdevhub-ngx-tw-card.d.ts +48 -0
  128. package/types/cdevhub-ngx-tw-carousel.d.ts +406 -0
  129. package/types/cdevhub-ngx-tw-checkbox.d.ts +136 -0
  130. package/types/cdevhub-ngx-tw-code-block.d.ts +93 -0
  131. package/types/cdevhub-ngx-tw-collapsible.d.ts +151 -0
  132. package/types/cdevhub-ngx-tw-combobox.d.ts +389 -0
  133. package/types/cdevhub-ngx-tw-command-palette.d.ts +215 -0
  134. package/types/cdevhub-ngx-tw-core.d.ts +719 -0
  135. package/types/cdevhub-ngx-tw-date-picker.d.ts +317 -0
  136. package/types/cdevhub-ngx-tw-date-range-picker.d.ts +313 -0
  137. package/types/cdevhub-ngx-tw-dialog.d.ts +303 -0
  138. package/types/cdevhub-ngx-tw-empty-state.d.ts +104 -0
  139. package/types/cdevhub-ngx-tw-flip-card.d.ts +95 -0
  140. package/types/cdevhub-ngx-tw-form-field.d.ts +210 -0
  141. package/types/cdevhub-ngx-tw-icon-lucide.d.ts +29 -0
  142. package/types/cdevhub-ngx-tw-icon.d.ts +134 -0
  143. package/types/cdevhub-ngx-tw-input.d.ts +110 -0
  144. package/types/cdevhub-ngx-tw-item.d.ts +70 -0
  145. package/types/cdevhub-ngx-tw-menu.d.ts +99 -0
  146. package/types/cdevhub-ngx-tw-paginator.d.ts +305 -0
  147. package/types/cdevhub-ngx-tw-popover.d.ts +157 -0
  148. package/types/cdevhub-ngx-tw-progress-bar.d.ts +100 -0
  149. package/types/cdevhub-ngx-tw-radio.d.ts +174 -0
  150. package/types/cdevhub-ngx-tw-segmented-control.d.ts +66 -0
  151. package/types/cdevhub-ngx-tw-select.d.ts +384 -0
  152. package/types/cdevhub-ngx-tw-separator.d.ts +28 -0
  153. package/types/cdevhub-ngx-tw-sheet.d.ts +335 -0
  154. package/types/cdevhub-ngx-tw-skeleton.d.ts +52 -0
  155. package/types/cdevhub-ngx-tw-slider.d.ts +258 -0
  156. package/types/cdevhub-ngx-tw-sort.d.ts +136 -0
  157. package/types/cdevhub-ngx-tw-spinner.d.ts +50 -0
  158. package/types/cdevhub-ngx-tw-split.d.ts +265 -0
  159. package/types/cdevhub-ngx-tw-stat.d.ts +140 -0
  160. package/types/cdevhub-ngx-tw-stepper.d.ts +127 -0
  161. package/types/cdevhub-ngx-tw-switch.d.ts +88 -0
  162. package/types/cdevhub-ngx-tw-tab-nav.d.ts +107 -0
  163. package/types/cdevhub-ngx-tw-table.d.ts +479 -0
  164. package/types/cdevhub-ngx-tw-tabs.d.ts +121 -0
  165. package/types/cdevhub-ngx-tw-textarea.d.ts +62 -0
  166. package/types/cdevhub-ngx-tw-theme.d.ts +106 -0
  167. package/types/cdevhub-ngx-tw-time-picker.d.ts +303 -0
  168. package/types/cdevhub-ngx-tw-timeline.d.ts +278 -0
  169. package/types/cdevhub-ngx-tw-toast.d.ts +388 -0
  170. package/types/cdevhub-ngx-tw-tooltip.d.ts +95 -0
  171. package/types/cdevhub-ngx-tw.d.ts +49 -0
@@ -0,0 +1,417 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, Injectable, makeEnvironmentProviders } from '@angular/core';
3
+ import { Settings, DateTime, Info } from 'luxon';
4
+ import { DateAdapter, TZ_OVERRIDE, DATE_ADAPTER } from '@cdevhub/ngx-tw/calendar';
5
+
6
+ /**
7
+ * Luxon-backed `DateAdapter`. Honors the calendar's `TZ_OVERRIDE` injection
8
+ * token so `today()` resolves against the consumer-configured timezone, and
9
+ * implements the §20.2 TZ-aware virtuals (`getTimezone`, `withTimezone`,
10
+ * `isDST`, `resolveAmbiguous`).
11
+ *
12
+ * `create()` accepts **1-based** months (matching the abstract contract and
13
+ * Luxon's `DateTime.fromObject({ month })` convention), while `getMonth()`
14
+ * returns **0-based** months (also per the abstract contract — see
15
+ * `NativeDateAdapter`).
16
+ */
17
+ class LuxonDateAdapter extends DateAdapter {
18
+ /**
19
+ * Optional per-instance timezone override (§4.3, §7.4). Resolved lazily so
20
+ * the constructor stays SSR-safe — Luxon's default zone reads from the host
21
+ * environment which we want to defer until first use.
22
+ */
23
+ _tzOverride = inject(TZ_OVERRIDE, { optional: true });
24
+ /**
25
+ * Locale is resolved lazily on first read so the constructor stays
26
+ * SSR-safe (no `navigator` access at class-construction time — §31.1).
27
+ */
28
+ _locale = null;
29
+ get locale() {
30
+ if (this._locale !== null)
31
+ return this._locale;
32
+ this._locale =
33
+ typeof navigator !== 'undefined' && typeof navigator.language === 'string'
34
+ ? navigator.language
35
+ : Settings.defaultLocale ?? 'en-US';
36
+ return this._locale;
37
+ }
38
+ /**
39
+ * Returns the configured timezone for new dates. Precedence: per-instance
40
+ * `TZ_OVERRIDE` → Luxon's `Settings.defaultZone` → `'local'`.
41
+ */
42
+ get zone() {
43
+ if (this._tzOverride)
44
+ return this._tzOverride;
45
+ const def = Settings.defaultZone;
46
+ // `Settings.defaultZone` is a `Zone` instance — fall back to its name.
47
+ return def && typeof def !== 'string' ? def.name : 'local';
48
+ }
49
+ /** Builds a `DateTime` in the adapter's configured zone + locale. */
50
+ inZone(dt) {
51
+ return dt.setZone(this.zone).setLocale(this.locale);
52
+ }
53
+ today() {
54
+ return DateTime.now().setZone(this.zone).setLocale(this.locale).startOf('day');
55
+ }
56
+ /**
57
+ * Constructs a `DateTime`. **`month` is 1-based** — `create(2026, 1, 1)`
58
+ * yields January 1, 2026 at 00:00 in the adapter's configured zone.
59
+ */
60
+ create(year, month, day) {
61
+ return DateTime.fromObject({ year, month, day }, { zone: this.zone, locale: this.locale });
62
+ }
63
+ clone(date) {
64
+ // `DateTime` is immutable; reconstructing preserves zone/locale and
65
+ // matches the defensive-copy semantics of the abstract contract.
66
+ return DateTime.fromMillis(date.toMillis(), {
67
+ zone: date.zone,
68
+ locale: date.locale ?? this.locale,
69
+ });
70
+ }
71
+ setLocale(locale) {
72
+ this._locale = locale;
73
+ }
74
+ getLocale() {
75
+ return this.locale;
76
+ }
77
+ getYear(date) {
78
+ return date.year;
79
+ }
80
+ /**
81
+ * Returns the **0-based** month (0 = January, 11 = December) to match the
82
+ * abstract `DateAdapter` contract and the `NativeDateAdapter`. Luxon's
83
+ * `DateTime.month` is 1-based, so we subtract one.
84
+ */
85
+ getMonth(date) {
86
+ return date.month - 1;
87
+ }
88
+ getDate(date) {
89
+ return date.day;
90
+ }
91
+ /**
92
+ * Day of week mapped to the Sunday-based scheme used by the abstract
93
+ * contract: `0 = Sunday`, `6 = Saturday`. Luxon's `weekday` is
94
+ * `1 = Monday … 7 = Sunday`, so Sunday gets re-anchored to `0`.
95
+ */
96
+ getDayOfWeek(date) {
97
+ return date.weekday % 7;
98
+ }
99
+ getNumDaysInMonth(date) {
100
+ return date.daysInMonth ?? 0;
101
+ }
102
+ getHours(date) {
103
+ return date.hour;
104
+ }
105
+ getMinutes(date) {
106
+ return date.minute;
107
+ }
108
+ getSeconds(date) {
109
+ return date.second;
110
+ }
111
+ withTime(date, hours, minutes, seconds) {
112
+ return date.set({ hour: hours, minute: minutes, second: seconds, millisecond: 0 });
113
+ }
114
+ /**
115
+ * Locale-aware first day of week (§19.2). Mirrors `NativeDateAdapter` —
116
+ * derives from `Intl.Locale.getWeekInfo()` when available, falling back to
117
+ * Monday (`1`) when the locale is unknown to ICU. ICU/CLDR returns
118
+ * `1=Monday … 7=Sunday`; we normalize to the project's `0=Sunday … 6=Saturday`
119
+ * convention so both adapters report identical values for identical locales.
120
+ */
121
+ getFirstDayOfWeek() {
122
+ if (typeof Intl !== 'undefined' && typeof Intl.Locale === 'function') {
123
+ try {
124
+ const l = new Intl.Locale(this.locale);
125
+ const info = (l.getWeekInfo?.() ?? l.weekInfo);
126
+ if (info && typeof info.firstDay === 'number') {
127
+ return info.firstDay === 7 ? 0 : info.firstDay;
128
+ }
129
+ }
130
+ catch {
131
+ return 1;
132
+ }
133
+ }
134
+ return 1;
135
+ }
136
+ getMonthNames(style) {
137
+ return Info.months(style, { locale: this.locale });
138
+ }
139
+ /**
140
+ * Day-of-week names starting at Sunday. Luxon's `Info.weekdays` starts at
141
+ * Monday, so the array is rotated to put Sunday first to match the abstract
142
+ * contract (and the native adapter).
143
+ */
144
+ getDayOfWeekNames(style) {
145
+ const monStart = Info.weekdays(style, { locale: this.locale });
146
+ // `[Mon, Tue, Wed, Thu, Fri, Sat, Sun]` → `[Sun, Mon, Tue, Wed, Thu, Fri, Sat]`.
147
+ return [monStart[6], ...monStart.slice(0, 6)];
148
+ }
149
+ getDateNames(_style = 'short') {
150
+ // Use a 31-day reference month to localize numerals where needed.
151
+ const ref = DateTime.fromObject({ year: 2017, month: 1, day: 1 }, { zone: 'utc', locale: this.locale });
152
+ return Array.from({ length: 31 }, (_, i) => ref.plus({ days: i }).toFormat('d'));
153
+ }
154
+ getYearName(date) {
155
+ return date.toFormat('yyyy', { locale: this.locale });
156
+ }
157
+ /**
158
+ * Formats a date for display.
159
+ *
160
+ * Accepts either a Luxon token string (e.g. `'yyyy-LL-dd'`), a
161
+ * {@link TwLuxonDateFormat} descriptor, or a Luxon preset bag
162
+ * (`Intl.DateTimeFormatOptions`). When no format is supplied the
163
+ * adapter falls back to a locale-aware medium date.
164
+ */
165
+ format(date, displayFormat) {
166
+ if (!this.isValid(date))
167
+ return '';
168
+ const localized = date.setLocale(this.locale);
169
+ if (typeof displayFormat === 'string') {
170
+ return localized.toFormat(displayFormat);
171
+ }
172
+ if (displayFormat && typeof displayFormat === 'object') {
173
+ const desc = displayFormat;
174
+ if (typeof desc.format === 'string') {
175
+ return localized.toFormat(desc.format);
176
+ }
177
+ if (desc.preset) {
178
+ return localized.toLocaleString(desc.preset);
179
+ }
180
+ // Treat a bare option-bag as a preset.
181
+ return localized.toLocaleString(displayFormat);
182
+ }
183
+ return localized.toLocaleString(DateTime.DATE_MED);
184
+ }
185
+ addYears(date, years) {
186
+ return date.plus({ years });
187
+ }
188
+ addMonths(date, months) {
189
+ return date.plus({ months });
190
+ }
191
+ addDays(date, days) {
192
+ return date.plus({ days });
193
+ }
194
+ addHours(date, hours) {
195
+ return date.plus({ hours });
196
+ }
197
+ addMinutes(date, minutes) {
198
+ return date.plus({ minutes });
199
+ }
200
+ compare(first, second) {
201
+ // Compare by calendar fields (year/month/day) so two `DateTime` instances
202
+ // representing the same wall-clock date in different zones still compare
203
+ // equal — matches the native adapter's behaviour.
204
+ return (first.year - second.year ||
205
+ first.month - second.month ||
206
+ first.day - second.day);
207
+ }
208
+ sameDate(first, second) {
209
+ if (first && second) {
210
+ const f = this.isValid(first);
211
+ const s = this.isValid(second);
212
+ if (f && s)
213
+ return this.compare(first, second) === 0;
214
+ return f === s;
215
+ }
216
+ return first === second;
217
+ }
218
+ /**
219
+ * Start-of-day normalization in the adapter's zone. Luxon's `startOf('day')`
220
+ * is DST-aware — on spring-forward days it returns the wall-clock instant the
221
+ * zone considers the first valid moment of the day.
222
+ */
223
+ startOfDay(date) {
224
+ return date.setZone(this.zone).startOf('day');
225
+ }
226
+ isValid(date) {
227
+ return date instanceof DateTime && date.isValid;
228
+ }
229
+ /** Returns Luxon's invalid sentinel (an invalid `DateTime`). */
230
+ invalid() {
231
+ return DateTime.invalid('invalid');
232
+ }
233
+ /**
234
+ * Parses a value into a `DateTime`. Accepts:
235
+ * - `DateTime` (cloned),
236
+ * - JS `Date` (re-anchored to the adapter's zone + locale),
237
+ * - number (epoch milliseconds),
238
+ * - string — when `parseFormat` is a Luxon token, uses `fromFormat`;
239
+ * otherwise parses strict ISO 8601 only.
240
+ *
241
+ * The free-form-string path is intentionally narrow: SQL and RFC 2822
242
+ * fallbacks were dropped so the Luxon adapter's acceptance surface matches
243
+ * `NativeDateAdapter.parse()` (which only accepts strings parseable by
244
+ * `new Date(value)`). Callers that need bespoke string formats should pass
245
+ * an explicit `parseFormat` token.
246
+ *
247
+ * Returns `null` on empty input or unrecognised value types, mirroring the
248
+ * native adapter's contract.
249
+ */
250
+ parse(value, parseFormat) {
251
+ if (value == null)
252
+ return null;
253
+ if (value instanceof DateTime) {
254
+ return value.isValid ? this.clone(value) : null;
255
+ }
256
+ if (value instanceof Date) {
257
+ const dt = DateTime.fromJSDate(value, { zone: this.zone }).setLocale(this.locale);
258
+ return dt.isValid ? dt : null;
259
+ }
260
+ if (typeof value === 'number') {
261
+ const dt = DateTime.fromMillis(value, { zone: this.zone, locale: this.locale });
262
+ return dt.isValid ? dt : null;
263
+ }
264
+ if (typeof value === 'string') {
265
+ if (!value.trim())
266
+ return null;
267
+ const opts = { zone: this.zone, locale: this.locale };
268
+ if (typeof parseFormat === 'string') {
269
+ const dt = DateTime.fromFormat(value, parseFormat, opts);
270
+ return dt.isValid ? dt : null;
271
+ }
272
+ if (parseFormat && typeof parseFormat === 'object') {
273
+ const desc = parseFormat;
274
+ if (typeof desc.format === 'string') {
275
+ const dt = DateTime.fromFormat(value, desc.format, opts);
276
+ return dt.isValid ? dt : null;
277
+ }
278
+ }
279
+ const iso = DateTime.fromISO(value, opts);
280
+ return iso.isValid ? iso : null;
281
+ }
282
+ return null;
283
+ }
284
+ /**
285
+ * Coerce an incoming form value. Returns `null` for empty input, an invalid
286
+ * `DateTime` sentinel for malformed input (so validators can flag it), and a
287
+ * cloned valid `DateTime` otherwise.
288
+ */
289
+ deserialize(value) {
290
+ if (value == null || value === '')
291
+ return null;
292
+ if (value instanceof DateTime) {
293
+ return value.isValid ? this.clone(value) : this.invalid();
294
+ }
295
+ const parsed = this.parse(value);
296
+ if (parsed && parsed.isValid)
297
+ return parsed;
298
+ return this.invalid();
299
+ }
300
+ /**
301
+ * ISO 8601 date serialization (`YYYY-MM-DD`). Calendar dates have no
302
+ * time component — `toIso` returns just the date portion.
303
+ */
304
+ toIso(date) {
305
+ return date.toFormat('yyyy-LL-dd');
306
+ }
307
+ /**
308
+ * Parses an ISO-8601 string to a `DateTime`. Overrides the base
309
+ * implementation to use Luxon's optimised `fromISO` parser.
310
+ */
311
+ fromIso(iso) {
312
+ if (typeof iso !== 'string' || !iso.trim())
313
+ return null;
314
+ const dt = DateTime.fromISO(iso, { zone: this.zone, locale: this.locale });
315
+ return dt.isValid ? dt : null;
316
+ }
317
+ // ---------------------------------------------------------------------------
318
+ // TZ-aware virtuals (§20.2). Luxon's `DateTime` carries zone information, so
319
+ // these are real implementations rather than the floating no-ops in the base
320
+ // class.
321
+ // ---------------------------------------------------------------------------
322
+ /** Returns the adapter's configured IANA zone name (e.g. `'America/New_York'`). */
323
+ getTimezone() {
324
+ return this.zone;
325
+ }
326
+ /** Returns a copy of `date` reinterpreted in `tz`. */
327
+ withTimezone(date, tz) {
328
+ return date.setZone(tz);
329
+ }
330
+ /** Whether `date` is currently observing daylight-saving time in its zone. */
331
+ isDST(date) {
332
+ return date.isInDST;
333
+ }
334
+ /**
335
+ * Resolves an ambiguous wall-clock time during DST fall-back. On fall-back
336
+ * days a single wall-clock hour repeats — e.g. 2024-11-03 01:30 in
337
+ * `America/New_York` happens once at offset -04:00 (EDT) and again at
338
+ * offset -05:00 (EST). Luxon's `DateTime.fromObject({...}, { zone })` always
339
+ * returns the **earlier** of the two candidates, so we reconstruct the
340
+ * "later" occurrence explicitly: rebuild the candidate at the date's
341
+ * wall-clock fields (anchoring it on the earlier occurrence) and add one
342
+ * hour to land on the same wall-clock's second occurrence in the
343
+ * post-fall-back offset.
344
+ *
345
+ * Non-ambiguous wall-clocks return unchanged for both `prefer` values:
346
+ * after `plus({ hour: 1 })` the wall-clock hour increments (no DST
347
+ * repetition), so the candidate is rejected and we return `date` as-is.
348
+ */
349
+ resolveAmbiguous(date, prefer) {
350
+ if (!date.isValid)
351
+ return date;
352
+ // Re-anchor on the earlier of the two candidates by reconstructing the
353
+ // wall-clock from `date`'s fields in its current zone. Luxon's
354
+ // `fromObject` deterministically picks the earlier instant when the
355
+ // input wall-clock is ambiguous, regardless of which occurrence `date`
356
+ // happens to represent.
357
+ const zone = date.zoneName ?? this.zone;
358
+ const earlier = DateTime.fromObject({
359
+ year: date.year,
360
+ month: date.month,
361
+ day: date.day,
362
+ hour: date.hour,
363
+ minute: date.minute,
364
+ second: date.second,
365
+ millisecond: date.millisecond,
366
+ }, { zone, locale: date.locale ?? this.locale });
367
+ if (!earlier.isValid)
368
+ return date;
369
+ if (prefer === 'earlier')
370
+ return earlier;
371
+ // Advancing one hour from the earlier-occurrence instant lands on the
372
+ // same wall-clock at the post-fall-back offset on ambiguous hours, and
373
+ // increments the wall-clock by one on non-ambiguous hours. Compare
374
+ // wall-clock fields to distinguish the two cases.
375
+ const later = earlier.plus({ hours: 1 });
376
+ if (later.hour === earlier.hour &&
377
+ later.day === earlier.day &&
378
+ later.month === earlier.month &&
379
+ later.year === earlier.year) {
380
+ return later;
381
+ }
382
+ return earlier;
383
+ }
384
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: LuxonDateAdapter, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
385
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: LuxonDateAdapter });
386
+ }
387
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: LuxonDateAdapter, decorators: [{
388
+ type: Injectable
389
+ }] });
390
+
391
+ /**
392
+ * Provides {@link LuxonDateAdapter} as the calendar's `DateAdapter`.
393
+ *
394
+ * Wire at app or route level so the adapter stays constant for the
395
+ * component's lifetime (§11.7 of the calendar spec):
396
+ *
397
+ * ```ts
398
+ * import { provideLuxonDateAdapter } from '@cdevhub/ngx-tw/calendar/luxon';
399
+ *
400
+ * bootstrapApplication(AppComponent, {
401
+ * providers: [provideLuxonDateAdapter()],
402
+ * });
403
+ * ```
404
+ */
405
+ function provideLuxonDateAdapter() {
406
+ return makeEnvironmentProviders([
407
+ LuxonDateAdapter,
408
+ { provide: DATE_ADAPTER, useExisting: LuxonDateAdapter },
409
+ ]);
410
+ }
411
+
412
+ /**
413
+ * Generated bundle index. Do not edit.
414
+ */
415
+
416
+ export { LuxonDateAdapter, provideLuxonDateAdapter };
417
+ //# sourceMappingURL=cdevhub-ngx-tw-calendar-luxon.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdevhub-ngx-tw-calendar-luxon.mjs","sources":["../../../projects/ngx-tw/calendar/luxon/luxon-date-adapter.ts","../../../projects/ngx-tw/calendar/luxon/provide-luxon-date-adapter.ts","../../../projects/ngx-tw/calendar/luxon/cdevhub-ngx-tw-calendar-luxon.ts"],"sourcesContent":["import { Injectable, inject } from '@angular/core';\nimport { DateTime, Info, Settings } from 'luxon';\nimport { DateAdapter, TZ_OVERRIDE, type TwDateNameStyle } from '@cdevhub/ngx-tw/calendar';\n\n/**\n * Display-format descriptor used by `LuxonDateAdapter.format()` and\n * `LuxonDateAdapter.parse()`.\n *\n * Two shapes are supported:\n * - `{ format: 'yyyy-LL-dd' }` — a Luxon `toFormat`/`fromFormat` token string.\n * - `{ preset: DateTime.DATE_FULL }` — a Luxon preset (an `Intl.DateTimeFormatOptions` bag).\n *\n * If both are provided, `format` (the explicit token) wins.\n */\nexport interface TwLuxonDateFormat {\n /** Luxon token string consumed by `DateTime#toFormat` / `DateTime.fromFormat`. */\n readonly format?: string;\n /** Luxon preset (e.g. `DateTime.DATE_FULL`) consumed by `DateTime#toLocaleString`. */\n readonly preset?: Intl.DateTimeFormatOptions;\n}\n\n/**\n * Luxon-backed `DateAdapter`. Honors the calendar's `TZ_OVERRIDE` injection\n * token so `today()` resolves against the consumer-configured timezone, and\n * implements the §20.2 TZ-aware virtuals (`getTimezone`, `withTimezone`,\n * `isDST`, `resolveAmbiguous`).\n *\n * `create()` accepts **1-based** months (matching the abstract contract and\n * Luxon's `DateTime.fromObject({ month })` convention), while `getMonth()`\n * returns **0-based** months (also per the abstract contract — see\n * `NativeDateAdapter`).\n */\n@Injectable()\nexport class LuxonDateAdapter extends DateAdapter<DateTime> {\n /**\n * Optional per-instance timezone override (§4.3, §7.4). Resolved lazily so\n * the constructor stays SSR-safe — Luxon's default zone reads from the host\n * environment which we want to defer until first use.\n */\n private readonly _tzOverride = inject(TZ_OVERRIDE, { optional: true });\n\n /**\n * Locale is resolved lazily on first read so the constructor stays\n * SSR-safe (no `navigator` access at class-construction time — §31.1).\n */\n private _locale: string | null = null;\n\n private get locale(): string {\n if (this._locale !== null) return this._locale;\n this._locale =\n typeof navigator !== 'undefined' && typeof navigator.language === 'string'\n ? navigator.language\n : Settings.defaultLocale ?? 'en-US';\n return this._locale;\n }\n\n /**\n * Returns the configured timezone for new dates. Precedence: per-instance\n * `TZ_OVERRIDE` → Luxon's `Settings.defaultZone` → `'local'`.\n */\n private get zone(): string {\n if (this._tzOverride) return this._tzOverride;\n const def = Settings.defaultZone;\n // `Settings.defaultZone` is a `Zone` instance — fall back to its name.\n return def && typeof def !== 'string' ? def.name : 'local';\n }\n\n /** Builds a `DateTime` in the adapter's configured zone + locale. */\n private inZone(dt: DateTime): DateTime {\n return dt.setZone(this.zone).setLocale(this.locale);\n }\n\n today(): DateTime {\n return DateTime.now().setZone(this.zone).setLocale(this.locale).startOf('day');\n }\n\n /**\n * Constructs a `DateTime`. **`month` is 1-based** — `create(2026, 1, 1)`\n * yields January 1, 2026 at 00:00 in the adapter's configured zone.\n */\n create(year: number, month: number, day: number): DateTime {\n return DateTime.fromObject(\n { year, month, day },\n { zone: this.zone, locale: this.locale },\n );\n }\n\n clone(date: DateTime): DateTime {\n // `DateTime` is immutable; reconstructing preserves zone/locale and\n // matches the defensive-copy semantics of the abstract contract.\n return DateTime.fromMillis(date.toMillis(), {\n zone: date.zone,\n locale: date.locale ?? this.locale,\n });\n }\n\n setLocale(locale: string): void {\n this._locale = locale;\n }\n\n getLocale(): string {\n return this.locale;\n }\n\n getYear(date: DateTime): number {\n return date.year;\n }\n\n /**\n * Returns the **0-based** month (0 = January, 11 = December) to match the\n * abstract `DateAdapter` contract and the `NativeDateAdapter`. Luxon's\n * `DateTime.month` is 1-based, so we subtract one.\n */\n getMonth(date: DateTime): number {\n return date.month - 1;\n }\n\n getDate(date: DateTime): number {\n return date.day;\n }\n\n /**\n * Day of week mapped to the Sunday-based scheme used by the abstract\n * contract: `0 = Sunday`, `6 = Saturday`. Luxon's `weekday` is\n * `1 = Monday … 7 = Sunday`, so Sunday gets re-anchored to `0`.\n */\n getDayOfWeek(date: DateTime): number {\n return date.weekday % 7;\n }\n\n getNumDaysInMonth(date: DateTime): number {\n return date.daysInMonth ?? 0;\n }\n\n getHours(date: DateTime): number {\n return date.hour;\n }\n\n getMinutes(date: DateTime): number {\n return date.minute;\n }\n\n getSeconds(date: DateTime): number {\n return date.second;\n }\n\n withTime(date: DateTime, hours: number, minutes: number, seconds: number): DateTime {\n return date.set({ hour: hours, minute: minutes, second: seconds, millisecond: 0 });\n }\n\n /**\n * Locale-aware first day of week (§19.2). Mirrors `NativeDateAdapter` —\n * derives from `Intl.Locale.getWeekInfo()` when available, falling back to\n * Monday (`1`) when the locale is unknown to ICU. ICU/CLDR returns\n * `1=Monday … 7=Sunday`; we normalize to the project's `0=Sunday … 6=Saturday`\n * convention so both adapters report identical values for identical locales.\n */\n getFirstDayOfWeek(): number {\n if (typeof Intl !== 'undefined' && typeof Intl.Locale === 'function') {\n try {\n const l = new Intl.Locale(this.locale) as Intl.Locale & {\n getWeekInfo?: () => { firstDay: number };\n weekInfo?: { firstDay: number };\n };\n const info = (l.getWeekInfo?.() ?? l.weekInfo) as { firstDay: number } | undefined;\n if (info && typeof info.firstDay === 'number') {\n return info.firstDay === 7 ? 0 : info.firstDay;\n }\n } catch {\n return 1;\n }\n }\n return 1;\n }\n\n getMonthNames(style: TwDateNameStyle): string[] {\n return Info.months(style, { locale: this.locale });\n }\n\n /**\n * Day-of-week names starting at Sunday. Luxon's `Info.weekdays` starts at\n * Monday, so the array is rotated to put Sunday first to match the abstract\n * contract (and the native adapter).\n */\n getDayOfWeekNames(style: TwDateNameStyle): string[] {\n const monStart = Info.weekdays(style, { locale: this.locale });\n // `[Mon, Tue, Wed, Thu, Fri, Sat, Sun]` → `[Sun, Mon, Tue, Wed, Thu, Fri, Sat]`.\n return [monStart[6], ...monStart.slice(0, 6)];\n }\n\n override getDateNames(_style: TwDateNameStyle = 'short'): string[] {\n // Use a 31-day reference month to localize numerals where needed.\n const ref = DateTime.fromObject(\n { year: 2017, month: 1, day: 1 },\n { zone: 'utc', locale: this.locale },\n );\n return Array.from({ length: 31 }, (_, i) => ref.plus({ days: i }).toFormat('d'));\n }\n\n getYearName(date: DateTime): string {\n return date.toFormat('yyyy', { locale: this.locale });\n }\n\n /**\n * Formats a date for display.\n *\n * Accepts either a Luxon token string (e.g. `'yyyy-LL-dd'`), a\n * {@link TwLuxonDateFormat} descriptor, or a Luxon preset bag\n * (`Intl.DateTimeFormatOptions`). When no format is supplied the\n * adapter falls back to a locale-aware medium date.\n */\n format(date: DateTime, displayFormat: unknown): string {\n if (!this.isValid(date)) return '';\n const localized = date.setLocale(this.locale);\n if (typeof displayFormat === 'string') {\n return localized.toFormat(displayFormat);\n }\n if (displayFormat && typeof displayFormat === 'object') {\n const desc = displayFormat as TwLuxonDateFormat;\n if (typeof desc.format === 'string') {\n return localized.toFormat(desc.format);\n }\n if (desc.preset) {\n return localized.toLocaleString(desc.preset);\n }\n // Treat a bare option-bag as a preset.\n return localized.toLocaleString(displayFormat as Intl.DateTimeFormatOptions);\n }\n return localized.toLocaleString(DateTime.DATE_MED);\n }\n\n addYears(date: DateTime, years: number): DateTime {\n return date.plus({ years });\n }\n\n addMonths(date: DateTime, months: number): DateTime {\n return date.plus({ months });\n }\n\n addDays(date: DateTime, days: number): DateTime {\n return date.plus({ days });\n }\n\n override addHours(date: DateTime, hours: number): DateTime {\n return date.plus({ hours });\n }\n\n addMinutes(date: DateTime, minutes: number): DateTime {\n return date.plus({ minutes });\n }\n\n compare(first: DateTime, second: DateTime): number {\n // Compare by calendar fields (year/month/day) so two `DateTime` instances\n // representing the same wall-clock date in different zones still compare\n // equal — matches the native adapter's behaviour.\n return (\n first.year - second.year ||\n first.month - second.month ||\n first.day - second.day\n );\n }\n\n sameDate(\n first: DateTime | null | undefined,\n second: DateTime | null | undefined,\n ): boolean {\n if (first && second) {\n const f = this.isValid(first);\n const s = this.isValid(second);\n if (f && s) return this.compare(first, second) === 0;\n return f === s;\n }\n return first === second;\n }\n\n /**\n * Start-of-day normalization in the adapter's zone. Luxon's `startOf('day')`\n * is DST-aware — on spring-forward days it returns the wall-clock instant the\n * zone considers the first valid moment of the day.\n */\n startOfDay(date: DateTime): DateTime {\n return date.setZone(this.zone).startOf('day');\n }\n\n isValid(date: DateTime): boolean {\n return date instanceof DateTime && date.isValid;\n }\n\n /** Returns Luxon's invalid sentinel (an invalid `DateTime`). */\n invalid(): DateTime {\n return DateTime.invalid('invalid');\n }\n\n /**\n * Parses a value into a `DateTime`. Accepts:\n * - `DateTime` (cloned),\n * - JS `Date` (re-anchored to the adapter's zone + locale),\n * - number (epoch milliseconds),\n * - string — when `parseFormat` is a Luxon token, uses `fromFormat`;\n * otherwise parses strict ISO 8601 only.\n *\n * The free-form-string path is intentionally narrow: SQL and RFC 2822\n * fallbacks were dropped so the Luxon adapter's acceptance surface matches\n * `NativeDateAdapter.parse()` (which only accepts strings parseable by\n * `new Date(value)`). Callers that need bespoke string formats should pass\n * an explicit `parseFormat` token.\n *\n * Returns `null` on empty input or unrecognised value types, mirroring the\n * native adapter's contract.\n */\n parse(value: unknown, parseFormat?: unknown): DateTime | null {\n if (value == null) return null;\n if (value instanceof DateTime) {\n return value.isValid ? this.clone(value) : null;\n }\n if (value instanceof Date) {\n const dt = DateTime.fromJSDate(value, { zone: this.zone }).setLocale(this.locale);\n return dt.isValid ? dt : null;\n }\n if (typeof value === 'number') {\n const dt = DateTime.fromMillis(value, { zone: this.zone, locale: this.locale });\n return dt.isValid ? dt : null;\n }\n if (typeof value === 'string') {\n if (!value.trim()) return null;\n const opts = { zone: this.zone, locale: this.locale };\n if (typeof parseFormat === 'string') {\n const dt = DateTime.fromFormat(value, parseFormat, opts);\n return dt.isValid ? dt : null;\n }\n if (parseFormat && typeof parseFormat === 'object') {\n const desc = parseFormat as TwLuxonDateFormat;\n if (typeof desc.format === 'string') {\n const dt = DateTime.fromFormat(value, desc.format, opts);\n return dt.isValid ? dt : null;\n }\n }\n const iso = DateTime.fromISO(value, opts);\n return iso.isValid ? iso : null;\n }\n return null;\n }\n\n /**\n * Coerce an incoming form value. Returns `null` for empty input, an invalid\n * `DateTime` sentinel for malformed input (so validators can flag it), and a\n * cloned valid `DateTime` otherwise.\n */\n deserialize(value: unknown): DateTime | null {\n if (value == null || value === '') return null;\n if (value instanceof DateTime) {\n return value.isValid ? this.clone(value) : this.invalid();\n }\n const parsed = this.parse(value);\n if (parsed && parsed.isValid) return parsed;\n return this.invalid();\n }\n\n /**\n * ISO 8601 date serialization (`YYYY-MM-DD`). Calendar dates have no\n * time component — `toIso` returns just the date portion.\n */\n toIso(date: DateTime): string {\n return date.toFormat('yyyy-LL-dd');\n }\n\n /**\n * Parses an ISO-8601 string to a `DateTime`. Overrides the base\n * implementation to use Luxon's optimised `fromISO` parser.\n */\n override fromIso(iso: string): DateTime | null {\n if (typeof iso !== 'string' || !iso.trim()) return null;\n const dt = DateTime.fromISO(iso, { zone: this.zone, locale: this.locale });\n return dt.isValid ? dt : null;\n }\n\n // ---------------------------------------------------------------------------\n // TZ-aware virtuals (§20.2). Luxon's `DateTime` carries zone information, so\n // these are real implementations rather than the floating no-ops in the base\n // class.\n // ---------------------------------------------------------------------------\n\n /** Returns the adapter's configured IANA zone name (e.g. `'America/New_York'`). */\n override getTimezone(): string {\n return this.zone;\n }\n\n /** Returns a copy of `date` reinterpreted in `tz`. */\n override withTimezone(date: DateTime, tz: string): DateTime {\n return date.setZone(tz);\n }\n\n /** Whether `date` is currently observing daylight-saving time in its zone. */\n override isDST(date: DateTime): boolean {\n return date.isInDST;\n }\n\n /**\n * Resolves an ambiguous wall-clock time during DST fall-back. On fall-back\n * days a single wall-clock hour repeats — e.g. 2024-11-03 01:30 in\n * `America/New_York` happens once at offset -04:00 (EDT) and again at\n * offset -05:00 (EST). Luxon's `DateTime.fromObject({...}, { zone })` always\n * returns the **earlier** of the two candidates, so we reconstruct the\n * \"later\" occurrence explicitly: rebuild the candidate at the date's\n * wall-clock fields (anchoring it on the earlier occurrence) and add one\n * hour to land on the same wall-clock's second occurrence in the\n * post-fall-back offset.\n *\n * Non-ambiguous wall-clocks return unchanged for both `prefer` values:\n * after `plus({ hour: 1 })` the wall-clock hour increments (no DST\n * repetition), so the candidate is rejected and we return `date` as-is.\n */\n override resolveAmbiguous(date: DateTime, prefer: 'earlier' | 'later'): DateTime {\n if (!date.isValid) return date;\n // Re-anchor on the earlier of the two candidates by reconstructing the\n // wall-clock from `date`'s fields in its current zone. Luxon's\n // `fromObject` deterministically picks the earlier instant when the\n // input wall-clock is ambiguous, regardless of which occurrence `date`\n // happens to represent.\n const zone = date.zoneName ?? this.zone;\n const earlier = DateTime.fromObject(\n {\n year: date.year,\n month: date.month,\n day: date.day,\n hour: date.hour,\n minute: date.minute,\n second: date.second,\n millisecond: date.millisecond,\n },\n { zone, locale: date.locale ?? this.locale },\n );\n if (!earlier.isValid) return date;\n if (prefer === 'earlier') return earlier;\n // Advancing one hour from the earlier-occurrence instant lands on the\n // same wall-clock at the post-fall-back offset on ambiguous hours, and\n // increments the wall-clock by one on non-ambiguous hours. Compare\n // wall-clock fields to distinguish the two cases.\n const later = earlier.plus({ hours: 1 });\n if (\n later.hour === earlier.hour &&\n later.day === earlier.day &&\n later.month === earlier.month &&\n later.year === earlier.year\n ) {\n return later;\n }\n return earlier;\n }\n}\n","import { type EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { DATE_ADAPTER } from '@cdevhub/ngx-tw/calendar';\nimport { LuxonDateAdapter } from './luxon-date-adapter';\n\n/**\n * Provides {@link LuxonDateAdapter} as the calendar's `DateAdapter`.\n *\n * Wire at app or route level so the adapter stays constant for the\n * component's lifetime (§11.7 of the calendar spec):\n *\n * ```ts\n * import { provideLuxonDateAdapter } from '@cdevhub/ngx-tw/calendar/luxon';\n *\n * bootstrapApplication(AppComponent, {\n * providers: [provideLuxonDateAdapter()],\n * });\n * ```\n */\nexport function provideLuxonDateAdapter(): EnvironmentProviders {\n return makeEnvironmentProviders([\n LuxonDateAdapter,\n { provide: DATE_ADAPTER, useExisting: LuxonDateAdapter },\n ]);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}