@tzslot/angular 0.1.0-beta.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.
@@ -0,0 +1,875 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, input, model, computed, signal, inject, ElementRef, effect, untracked, DestroyRef, forwardRef, ChangeDetectionStrategy, Component, viewChild, output } from '@angular/core';
3
+ import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
+ import { EN, getSlotChoices, createTimeSlots, createCalendar, createDateField, createDateRange, createDateTimeRange, createDailyRange, createMultiDate } from '@tzslot/dom';
5
+ export { EN, FR } from '@tzslot/dom';
6
+ import { Temporal, toPlainDate, fromPlainDate } from '@tzslot/core';
7
+
8
+ const TZSLOT_MESSAGES = new InjectionToken('tzslot.messages', {
9
+ providedIn: 'root',
10
+ factory: () => EN,
11
+ });
12
+ /** `providers: [provideTzslotMessages(FR)]` */
13
+ function provideTzslotMessages(messages) {
14
+ return { provide: TZSLOT_MESSAGES, useValue: messages };
15
+ }
16
+
17
+ /**
18
+ * `<tz-time-slots>` — the slot list from @tzslot/dom, spoken in Angular.
19
+ *
20
+ * What it selects is an `Instant`, never a wall time. A wall time is what a
21
+ * clock shows; an instant is when it happened. Only one of those can be stored.
22
+ */
23
+ class TimeSlotPicker {
24
+ constructor() {
25
+ /** The day to list, as a PlainDate or an ISO date string. */
26
+ this.date = input.required(...(ngDevMode ? [{ debugName: "date" }] : /* istanbul ignore next */ []));
27
+ /** An IANA identifier — 'Europe/Paris', not an offset. Offsets change twice a year. */
28
+ this.timeZone = input.required(...(ngDevMode ? [{ debugName: "timeZone" }] : /* istanbul ignore next */ []));
29
+ this.stepMinutes = input(30, ...(ngDevMode ? [{ debugName: "stepMinutes" }] : /* istanbul ignore next */ []));
30
+ /** The working day. Slots outside these bounds are not produced at all. */
31
+ this.minTime = input(undefined, ...(ngDevMode ? [{ debugName: "minTime" }] : /* istanbul ignore next */ []));
32
+ this.maxTime = input(undefined, ...(ngDevMode ? [{ debugName: "maxTime" }] : /* istanbul ignore next */ []));
33
+ /** Rules out individual slots while still showing them: booked, over capacity. */
34
+ this.isDisabled = input(undefined, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
35
+ /** Leave out the times that cannot happen, rather than showing them struck through. */
36
+ this.skipNonExistent = input(false, ...(ngDevMode ? [{ debugName: "skipNonExistent" }] : /* istanbul ignore next */ []));
37
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
38
+ /** What is selected, as a moment. Two-way: `[(value)]`. */
39
+ this.value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
40
+ this.ariaLabel = input(undefined, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
41
+ this.missingLabel = input(undefined, ...(ngDevMode ? [{ debugName: "missingLabel" }] : /* istanbul ignore next */ []));
42
+ this.emptyLabel = input(undefined, ...(ngDevMode ? [{ debugName: "emptyLabel" }] : /* istanbul ignore next */ []));
43
+ /** The rows listed, one per selectable moment: an ambiguous time gives two. */
44
+ this.choices = computed(() => getSlotChoices(this.date(), this.timeZone(), {
45
+ stepMinutes: this.stepMinutes(),
46
+ skipNonExistent: this.skipNonExistent(),
47
+ ...(this.minTime() !== undefined ? { minTime: this.minTime() } : {}),
48
+ ...(this.maxTime() !== undefined ? { maxTime: this.maxTime() } : {}),
49
+ ...(this.isDisabled() !== undefined ? { isDisabled: this.isDisabled() } : {}),
50
+ }), ...(ngDevMode ? [{ debugName: "choices" }] : /* istanbul ignore next */ []));
51
+ this.formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
52
+ this.messages = inject(TZSLOT_MESSAGES);
53
+ this.settings = computed(() => ({
54
+ date: this.date(),
55
+ timeZone: this.timeZone(),
56
+ stepMinutes: this.stepMinutes(),
57
+ minTime: this.minTime(),
58
+ maxTime: this.maxTime(),
59
+ isDisabled: this.isDisabled(),
60
+ skipNonExistent: this.skipNonExistent(),
61
+ disabled: this.disabled() || this.formDisabled(),
62
+ value: this.value(),
63
+ ariaLabel: this.ariaLabel(),
64
+ missingLabel: this.missingLabel(),
65
+ emptyLabel: this.emptyLabel(),
66
+ messages: this.messages,
67
+ }), ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
68
+ /**
69
+ * Created empty: `date` and `timeZone` are required inputs, which cannot be
70
+ * read before they are bound. The first change detection fills it in.
71
+ */
72
+ this.slots = createTimeSlots(inject(ElementRef).nativeElement, {
73
+ messages: this.messages,
74
+ onChange: (instant) => {
75
+ this.value.set(instant);
76
+ this.onChange(instant);
77
+ this.onTouched();
78
+ },
79
+ });
80
+ // ── ControlValueAccessor ────────────────────────────────────
81
+ this.onChange = () => { };
82
+ this.onTouched = () => { };
83
+ // The settings are read here, so the effect follows them; the call into the
84
+ // widget runs untracked. A widget may answer by calling back — closing a
85
+ // panel, say — and a callback that writes a signal inside an effect is an
86
+ // error on Angular 18 (NG0600), and a hidden dependency on any version.
87
+ effect(() => {
88
+ const settings = this.settings();
89
+ untracked(() => this.slots.update(settings));
90
+ });
91
+ inject(DestroyRef).onDestroy(() => this.slots.destroy());
92
+ }
93
+ /** Clears the selection and tells any form control about it. */
94
+ clear() {
95
+ this.slots.clear();
96
+ }
97
+ writeValue(value) {
98
+ this.value.set(value ?? null);
99
+ }
100
+ registerOnChange(fn) {
101
+ this.onChange = fn;
102
+ }
103
+ registerOnTouched(fn) {
104
+ this.onTouched = fn;
105
+ }
106
+ setDisabledState(isDisabled) {
107
+ this.formDisabled.set(isDisabled);
108
+ }
109
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: TimeSlotPicker, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
110
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.23", type: TimeSlotPicker, isStandalone: true, selector: "tz-time-slots", inputs: { date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: true, transformFunction: null }, timeZone: { classPropertyName: "timeZone", publicName: "timeZone", isSignal: true, isRequired: true, transformFunction: null }, stepMinutes: { classPropertyName: "stepMinutes", publicName: "stepMinutes", isSignal: true, isRequired: false, transformFunction: null }, minTime: { classPropertyName: "minTime", publicName: "minTime", isSignal: true, isRequired: false, transformFunction: null }, maxTime: { classPropertyName: "maxTime", publicName: "maxTime", isSignal: true, isRequired: false, transformFunction: null }, isDisabled: { classPropertyName: "isDisabled", publicName: "isDisabled", isSignal: true, isRequired: false, transformFunction: null }, skipNonExistent: { classPropertyName: "skipNonExistent", publicName: "skipNonExistent", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, missingLabel: { classPropertyName: "missingLabel", publicName: "missingLabel", isSignal: true, isRequired: false, transformFunction: null }, emptyLabel: { classPropertyName: "emptyLabel", publicName: "emptyLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, providers: [
111
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TimeSlotPicker), multi: true },
112
+ ], ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
113
+ }
114
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: TimeSlotPicker, decorators: [{
115
+ type: Component,
116
+ args: [{
117
+ selector: 'tz-time-slots',
118
+ standalone: true,
119
+ changeDetection: ChangeDetectionStrategy.OnPush,
120
+ providers: [
121
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TimeSlotPicker), multi: true },
122
+ ],
123
+ template: '',
124
+ }]
125
+ }], ctorParameters: () => [], propDecorators: { date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: true }] }], timeZone: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeZone", required: true }] }], stepMinutes: [{ type: i0.Input, args: [{ isSignal: true, alias: "stepMinutes", required: false }] }], minTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "minTime", required: false }] }], maxTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTime", required: false }] }], isDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDisabled", required: false }] }], skipNonExistent: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipNonExistent", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], missingLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "missingLabel", required: false }] }], emptyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyLabel", required: false }] }] } });
126
+
127
+ /**
128
+ * `<tz-calendar>` — the calendar from @tzslot/dom, spoken in Angular.
129
+ *
130
+ * Everything the user sees and does is drawn by `createCalendar`. This class
131
+ * only translates: inputs and models into `update()`, the calendar's callbacks
132
+ * into `valueChange` and form notifications, projected content into icons.
133
+ */
134
+ class Calendar {
135
+ constructor() {
136
+ /** The selected day. Two-way: `[(value)]`. */
137
+ this.value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
138
+ /** Monday by default, as ISO-8601 numbers the week. */
139
+ this.firstDayOfWeek = input(1, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : /* istanbul ignore next */ []));
140
+ /** A BCP-47 tag for the month and weekday names. Defaults to the browser's. */
141
+ this.locale = input(undefined, ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
142
+ this.min = input(null, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
143
+ this.max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
144
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
145
+ /**
146
+ * What the form control holds. 'temporal' by default; 'date' lets an
147
+ * existing FormControl<Date> keep working untouched, which is the whole of a
148
+ * flatpickr migration on most screens.
149
+ */
150
+ this.valueAs = input('temporal', ...(ngDevMode ? [{ debugName: "valueAs" }] : /* istanbul ignore next */ []));
151
+ /**
152
+ * The zone used to turn a Date into a calendar day and back. Only consulted
153
+ * when valueAs is 'date': which day an instant falls on depends on where you
154
+ * are standing, so it is explicit rather than guessed.
155
+ */
156
+ this.valueTimeZone = input(Temporal.Now.timeZoneId(), ...(ngDevMode ? [{ debugName: "valueTimeZone" }] : /* istanbul ignore next */ []));
157
+ /** Rules out individual days inside the range: closures, weekends, full days. */
158
+ this.isDateDisabled = input(undefined, ...(ngDevMode ? [{ debugName: "isDateDisabled" }] : /* istanbul ignore next */ []));
159
+ /** Today, injectable so a test does not depend on the day it runs. */
160
+ this.today = input(Temporal.Now.plainDateISO(), ...(ngDevMode ? [{ debugName: "today" }] : /* istanbul ignore next */ []));
161
+ /**
162
+ * Which level the grid is choosing between. A model, so a consumer can open
163
+ * straight on years — a birthdate picker should not start on this month.
164
+ */
165
+ this.view = model('days', ...(ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []));
166
+ /** 'months' turns this into a month picker, 'years' into a year picker. */
167
+ this.minView = input('days', ...(ngDevMode ? [{ debugName: "minView" }] : /* istanbul ignore next */ []));
168
+ /** Adds to each day: a price, places left, a class, a reason to rule it out. */
169
+ this.renderCell = input(undefined, ...(ngDevMode ? [{ debugName: "renderCell" }] : /* istanbul ignore next */ []));
170
+ /** Buttons under the grid: `['today', 'clear']`. None by default. */
171
+ this.buttons = input([], ...(ngDevMode ? [{ debugName: "buttons" }] : /* istanbul ignore next */ []));
172
+ this.host = inject(ElementRef).nativeElement;
173
+ this.messages = inject(TZSLOT_MESSAGES);
174
+ this.prevSlot = viewChild.required('prev');
175
+ this.nextSlot = viewChild.required('next');
176
+ this.formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
177
+ this.settings = computed(() => ({
178
+ value: this.value(),
179
+ view: this.view(),
180
+ minView: this.minView(),
181
+ firstDayOfWeek: this.firstDayOfWeek(),
182
+ locale: this.locale(),
183
+ min: this.min(),
184
+ max: this.max(),
185
+ disabled: this.disabled() || this.formDisabled(),
186
+ isDateDisabled: this.isDateDisabled(),
187
+ today: this.today(),
188
+ renderCell: this.renderCell(),
189
+ buttons: this.buttons(),
190
+ messages: this.messages,
191
+ }), ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
192
+ /**
193
+ * Drawn at construction, so the cells exist as soon as the component does —
194
+ * as they did when this was a template. Inputs are not bound yet at this
195
+ * point; the effect below brings them in on the first change detection.
196
+ */
197
+ this.calendar = createCalendar(this.host, {
198
+ ...untracked(this.settings),
199
+ onChange: (date) => {
200
+ this.value.set(date);
201
+ this.onChange(date);
202
+ this.onTouched();
203
+ },
204
+ onViewChange: (view) => this.view.set(view),
205
+ });
206
+ // ── ControlValueAccessor ────────────────────────────────────
207
+ this.onChange = () => { };
208
+ this.onTouched = () => { };
209
+ // The settings are read here, so the effect follows them; the call into the
210
+ // widget runs untracked. A widget may answer by calling back — closing a
211
+ // panel, say — and a callback that writes a signal inside an effect is an
212
+ // error on Angular 18 (NG0600), and a hidden dependency on any version.
213
+ effect(() => {
214
+ const settings = this.settings();
215
+ untracked(() => this.calendar.update(settings));
216
+ });
217
+ }
218
+ /** Projected content only exists once the view does. */
219
+ ngAfterViewInit() {
220
+ this.calendar.setIcons({
221
+ prev: this.projected(this.prevSlot()),
222
+ next: this.projected(this.nextSlot()),
223
+ });
224
+ }
225
+ ngOnDestroy() {
226
+ this.calendar.destroy();
227
+ }
228
+ /** Moves the grid without selecting anything — flatpickr's setViewDate. */
229
+ goTo(date) {
230
+ this.calendar.goTo({ year: date.year, month: date.month });
231
+ }
232
+ /** Clears the selection and tells any form control about it. */
233
+ clear() {
234
+ this.calendar.clear();
235
+ }
236
+ /** Whatever was projected into a slot, or undefined so the default chevron stays. */
237
+ projected(slot) {
238
+ const nodes = Array.from(slot.nativeElement.childNodes);
239
+ if (!nodes.some((n) => n.nodeType === Node.ELEMENT_NODE || n.textContent?.trim()))
240
+ return undefined;
241
+ const fragment = this.host.ownerDocument.createDocumentFragment();
242
+ fragment.append(...nodes);
243
+ return fragment;
244
+ }
245
+ writeValue(value) {
246
+ this.value.set(value === null || value === undefined ? null : toPlainDate(value, this.valueTimeZone()));
247
+ }
248
+ registerOnChange(fn) {
249
+ this.onChange = (date) => fn(fromPlainDate(date, this.valueAs(), this.valueTimeZone()));
250
+ }
251
+ registerOnTouched(fn) {
252
+ this.onTouched = fn;
253
+ }
254
+ setDisabledState(isDisabled) {
255
+ this.formDisabled.set(isDisabled);
256
+ }
257
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: Calendar, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
258
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.23", type: Calendar, isStandalone: true, selector: "tz-calendar", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, valueAs: { classPropertyName: "valueAs", publicName: "valueAs", isSignal: true, isRequired: false, transformFunction: null }, valueTimeZone: { classPropertyName: "valueTimeZone", publicName: "valueTimeZone", isSignal: true, isRequired: false, transformFunction: null }, isDateDisabled: { classPropertyName: "isDateDisabled", publicName: "isDateDisabled", isSignal: true, isRequired: false, transformFunction: null }, today: { classPropertyName: "today", publicName: "today", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null }, minView: { classPropertyName: "minView", publicName: "minView", isSignal: true, isRequired: false, transformFunction: null }, renderCell: { classPropertyName: "renderCell", publicName: "renderCell", isSignal: true, isRequired: false, transformFunction: null }, buttons: { classPropertyName: "buttons", publicName: "buttons", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", view: "viewChange" }, providers: [
259
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => Calendar), multi: true },
260
+ ], viewQueries: [{ propertyName: "prevSlot", first: true, predicate: ["prev"], descendants: true, isSignal: true }, { propertyName: "nextSlot", first: true, predicate: ["next"], descendants: true, isSignal: true }], ngImport: i0, template: `
261
+ <span #prev hidden><ng-content select="[tzPrev]" /></span>
262
+ <span #next hidden><ng-content select="[tzNext]" /></span>
263
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
264
+ }
265
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: Calendar, decorators: [{
266
+ type: Component,
267
+ args: [{
268
+ selector: 'tz-calendar',
269
+ standalone: true,
270
+ changeDetection: ChangeDetectionStrategy.OnPush,
271
+ providers: [
272
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => Calendar), multi: true },
273
+ ],
274
+ // The slots only collect projected icons; the calendar moves them into its
275
+ // buttons and the slots stay empty and hidden.
276
+ template: `
277
+ <span #prev hidden><ng-content select="[tzPrev]" /></span>
278
+ <span #next hidden><ng-content select="[tzNext]" /></span>
279
+ `,
280
+ }]
281
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], valueAs: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueAs", required: false }] }], valueTimeZone: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueTimeZone", required: false }] }], isDateDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDateDisabled", required: false }] }], today: [{ type: i0.Input, args: [{ isSignal: true, alias: "today", required: false }] }], view: [{ type: i0.Input, args: [{ isSignal: true, alias: "view", required: false }] }, { type: i0.Output, args: ["viewChange"] }], minView: [{ type: i0.Input, args: [{ isSignal: true, alias: "minView", required: false }] }], renderCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderCell", required: false }] }], buttons: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttons", required: false }] }], prevSlot: [{ type: i0.ViewChild, args: ['prev', { isSignal: true }] }], nextSlot: [{ type: i0.ViewChild, args: ['next', { isSignal: true }] }] } });
282
+
283
+ /**
284
+ * `<tz-date-field>` — the field from @tzslot/dom, spoken in Angular.
285
+ *
286
+ * The trigger, the panel, its position, focus and theme are all drawn by
287
+ * `createDateField`. This class maps inputs to `update()`, callbacks to
288
+ * `valueChange`, `opened`, `closed` and form notifications, and a projected
289
+ * `[tzIcon]` to the field's icon.
290
+ */
291
+ class DateField {
292
+ constructor() {
293
+ this.value = model(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
294
+ this.mode = input('popup', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
295
+ this.placeholder = input(undefined, ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
296
+ this.ariaLabel = input(undefined, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
297
+ this.locale = input(undefined, ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
298
+ this.firstDayOfWeek = input(1, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : /* istanbul ignore next */ []));
299
+ this.min = input(null, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
300
+ this.max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
301
+ this.isDateDisabled = input(undefined, ...(ngDevMode ? [{ debugName: "isDateDisabled" }] : /* istanbul ignore next */ []));
302
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
303
+ /**
304
+ * What the form control holds. 'temporal' by default; 'date' lets an
305
+ * existing FormControl<Date> keep working untouched, which is the whole of a
306
+ * flatpickr migration on most screens.
307
+ */
308
+ this.valueAs = input('temporal', ...(ngDevMode ? [{ debugName: "valueAs" }] : /* istanbul ignore next */ []));
309
+ /**
310
+ * The zone used to turn a Date into a calendar day and back. Only consulted
311
+ * when valueAs is 'date': which day an instant falls on depends on where you
312
+ * are standing, so it is explicit rather than guessed.
313
+ */
314
+ this.valueTimeZone = input(Temporal.Now.timeZoneId(), ...(ngDevMode ? [{ debugName: "valueTimeZone" }] : /* istanbul ignore next */ []));
315
+ /** How the chosen date is written in the field. Defaults to the locale's medium form. */
316
+ this.displayWith = input(undefined, ...(ngDevMode ? [{ debugName: "displayWith" }] : /* istanbul ignore next */ []));
317
+ /** Passed to the calendar in the panel. */
318
+ this.renderCell = input(undefined, ...(ngDevMode ? [{ debugName: "renderCell" }] : /* istanbul ignore next */ []));
319
+ /** Under the panel's grid: `['today', 'clear']`. Choosing either closes it. */
320
+ this.buttons = input([], ...(ngDevMode ? [{ debugName: "buttons" }] : /* istanbul ignore next */ []));
321
+ this.opened = output();
322
+ this.closed = output();
323
+ /** Whether the panel is showing. Readable from a ViewChild. */
324
+ this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
325
+ this.formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
326
+ this.host = inject(ElementRef).nativeElement;
327
+ this.messages = inject(TZSLOT_MESSAGES);
328
+ this.iconSlot = viewChild.required('icon');
329
+ this.settings = computed(() => ({
330
+ value: this.value(),
331
+ mode: this.mode(),
332
+ placeholder: this.placeholder(),
333
+ ariaLabel: this.ariaLabel(),
334
+ locale: this.locale(),
335
+ firstDayOfWeek: this.firstDayOfWeek(),
336
+ min: this.min(),
337
+ max: this.max(),
338
+ isDateDisabled: this.isDateDisabled(),
339
+ disabled: this.disabled() || this.formDisabled(),
340
+ displayWith: this.displayWith(),
341
+ renderCell: this.renderCell(),
342
+ buttons: this.buttons(),
343
+ messages: this.messages,
344
+ }), ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
345
+ this.field = createDateField(this.host, {
346
+ ...untracked(this.settings),
347
+ onChange: (date) => {
348
+ this.value.set(date);
349
+ this.onChange(date);
350
+ },
351
+ onOpen: () => {
352
+ this.isOpen.set(true);
353
+ this.onTouched();
354
+ this.opened.emit();
355
+ },
356
+ onClose: () => {
357
+ this.isOpen.set(false);
358
+ this.closed.emit();
359
+ },
360
+ });
361
+ // ── ControlValueAccessor ────────────────────────────────────
362
+ this.onChange = () => { };
363
+ this.onTouched = () => { };
364
+ // The settings are read here, so the effect follows them; the call into the
365
+ // widget runs untracked. A widget may answer by calling back — closing a
366
+ // panel, say — and a callback that writes a signal inside an effect is an
367
+ // error on Angular 18 (NG0600), and a hidden dependency on any version.
368
+ effect(() => {
369
+ const settings = this.settings();
370
+ untracked(() => this.field.update(settings));
371
+ });
372
+ inject(DestroyRef).onDestroy(() => this.field.destroy());
373
+ }
374
+ ngAfterViewInit() {
375
+ const slot = this.iconSlot().nativeElement;
376
+ if (Array.from(slot.childNodes).some((n) => n.nodeType === Node.ELEMENT_NODE || n.textContent?.trim())) {
377
+ const fragment = this.host.ownerDocument.createDocumentFragment();
378
+ fragment.append(...Array.from(slot.childNodes));
379
+ this.field.setIcon(fragment);
380
+ }
381
+ }
382
+ /**
383
+ * Opening and closing are public so a ViewChild can drive the field — a
384
+ * button elsewhere on the page, a wizard step, a keyboard shortcut.
385
+ */
386
+ toggle() {
387
+ this.field.toggle();
388
+ }
389
+ /** No-op when already open. */
390
+ open() {
391
+ this.field.open();
392
+ }
393
+ close() {
394
+ this.field.close();
395
+ }
396
+ /** Clears the selection and tells any form control about it. */
397
+ clear() {
398
+ this.field.clear();
399
+ }
400
+ writeValue(value) {
401
+ this.value.set(value === null || value === undefined ? null : toPlainDate(value, this.valueTimeZone()));
402
+ }
403
+ registerOnChange(fn) {
404
+ this.onChange = (date) => fn(fromPlainDate(date, this.valueAs(), this.valueTimeZone()));
405
+ }
406
+ registerOnTouched(fn) {
407
+ this.onTouched = fn;
408
+ }
409
+ setDisabledState(isDisabled) {
410
+ this.formDisabled.set(isDisabled);
411
+ }
412
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: DateField, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
413
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.23", type: DateField, isStandalone: true, selector: "tz-date-field", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, isDateDisabled: { classPropertyName: "isDateDisabled", publicName: "isDateDisabled", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, valueAs: { classPropertyName: "valueAs", publicName: "valueAs", isSignal: true, isRequired: false, transformFunction: null }, valueTimeZone: { classPropertyName: "valueTimeZone", publicName: "valueTimeZone", isSignal: true, isRequired: false, transformFunction: null }, displayWith: { classPropertyName: "displayWith", publicName: "displayWith", isSignal: true, isRequired: false, transformFunction: null }, renderCell: { classPropertyName: "renderCell", publicName: "renderCell", isSignal: true, isRequired: false, transformFunction: null }, buttons: { classPropertyName: "buttons", publicName: "buttons", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", opened: "opened", closed: "closed" }, providers: [
414
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateField), multi: true },
415
+ ], viewQueries: [{ propertyName: "iconSlot", first: true, predicate: ["icon"], descendants: true, isSignal: true }], ngImport: i0, template: `<span #icon hidden><ng-content select="[tzIcon]" /></span>`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
416
+ }
417
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: DateField, decorators: [{
418
+ type: Component,
419
+ args: [{
420
+ selector: 'tz-date-field',
421
+ standalone: true,
422
+ changeDetection: ChangeDetectionStrategy.OnPush,
423
+ providers: [
424
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateField), multi: true },
425
+ ],
426
+ template: `<span #icon hidden><ng-content select="[tzIcon]" /></span>`,
427
+ }]
428
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], isDateDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDateDisabled", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], valueAs: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueAs", required: false }] }], valueTimeZone: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueTimeZone", required: false }] }], displayWith: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayWith", required: false }] }], renderCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderCell", required: false }] }], buttons: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttons", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], iconSlot: [{ type: i0.ViewChild, args: ['icon', { isSignal: true }] }] } });
429
+
430
+ const EMPTY$2 = { start: null, end: null };
431
+ /** `<tz-date-range>` — the range from @tzslot/dom, spoken in Angular. */
432
+ class DateRange {
433
+ constructor() {
434
+ this.value = model(EMPTY$2, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
435
+ this.firstDayOfWeek = input(1, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : /* istanbul ignore next */ []));
436
+ this.locale = input(undefined, ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
437
+ this.min = input(null, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
438
+ this.max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
439
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
440
+ this.isDateDisabled = input(undefined, ...(ngDevMode ? [{ debugName: "isDateDisabled" }] : /* istanbul ignore next */ []));
441
+ this.today = input(Temporal.Now.plainDateISO(), ...(ngDevMode ? [{ debugName: "today" }] : /* istanbul ignore next */ []));
442
+ /** Refuse a range that steps over a day isDateDisabled rules out. On by default. */
443
+ this.blockAcrossDisabled = input(true, ...(ngDevMode ? [{ debugName: "blockAcrossDisabled" }] : /* istanbul ignore next */ []));
444
+ /** Adds to each day: a price per night, places left, a class of your own. */
445
+ this.renderCell = input(undefined, ...(ngDevMode ? [{ debugName: "renderCell" }] : /* istanbul ignore next */ []));
446
+ /** Overrides the bundle for this one instance. */
447
+ this.rangeSpansBlockedMessage = input(undefined, ...(ngDevMode ? [{ debugName: "rangeSpansBlockedMessage" }] : /* istanbul ignore next */ []));
448
+ this.formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
449
+ this.host = inject(ElementRef).nativeElement;
450
+ this.messages = inject(TZSLOT_MESSAGES);
451
+ this.prevSlot = viewChild.required('prev');
452
+ this.nextSlot = viewChild.required('next');
453
+ this.settings = computed(() => ({
454
+ value: this.value(),
455
+ firstDayOfWeek: this.firstDayOfWeek(),
456
+ locale: this.locale(),
457
+ min: this.min(),
458
+ max: this.max(),
459
+ disabled: this.disabled() || this.formDisabled(),
460
+ isDateDisabled: this.isDateDisabled(),
461
+ today: this.today(),
462
+ blockAcrossDisabled: this.blockAcrossDisabled(),
463
+ rangeSpansBlockedMessage: this.rangeSpansBlockedMessage(),
464
+ renderCell: this.renderCell(),
465
+ messages: this.messages,
466
+ }), ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
467
+ this.range = createDateRange(this.host, {
468
+ ...untracked(this.settings),
469
+ onChange: (next) => {
470
+ this.value.set(next);
471
+ this.onChange(next);
472
+ this.onTouched();
473
+ },
474
+ });
475
+ // ── ControlValueAccessor ────────────────────────────────────
476
+ this.onChange = () => { };
477
+ this.onTouched = () => { };
478
+ // The settings are read here, so the effect follows them; the call into the
479
+ // widget runs untracked. A widget may answer by calling back — closing a
480
+ // panel, say — and a callback that writes a signal inside an effect is an
481
+ // error on Angular 18 (NG0600), and a hidden dependency on any version.
482
+ effect(() => {
483
+ const settings = this.settings();
484
+ untracked(() => this.range.update(settings));
485
+ });
486
+ inject(DestroyRef).onDestroy(() => this.range.destroy());
487
+ }
488
+ ngAfterViewInit() {
489
+ this.range.setIcons({
490
+ prev: projected(this.host, this.prevSlot()),
491
+ next: projected(this.host, this.nextSlot()),
492
+ });
493
+ }
494
+ /** Clears the selection and tells any form control about it. */
495
+ clear() {
496
+ this.range.clear();
497
+ }
498
+ writeValue(value) {
499
+ this.value.set(value ?? EMPTY$2);
500
+ }
501
+ registerOnChange(fn) {
502
+ this.onChange = fn;
503
+ }
504
+ registerOnTouched(fn) {
505
+ this.onTouched = fn;
506
+ }
507
+ setDisabledState(isDisabled) {
508
+ this.formDisabled.set(isDisabled);
509
+ }
510
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: DateRange, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
511
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.23", type: DateRange, isStandalone: true, selector: "tz-date-range", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, isDateDisabled: { classPropertyName: "isDateDisabled", publicName: "isDateDisabled", isSignal: true, isRequired: false, transformFunction: null }, today: { classPropertyName: "today", publicName: "today", isSignal: true, isRequired: false, transformFunction: null }, blockAcrossDisabled: { classPropertyName: "blockAcrossDisabled", publicName: "blockAcrossDisabled", isSignal: true, isRequired: false, transformFunction: null }, renderCell: { classPropertyName: "renderCell", publicName: "renderCell", isSignal: true, isRequired: false, transformFunction: null }, rangeSpansBlockedMessage: { classPropertyName: "rangeSpansBlockedMessage", publicName: "rangeSpansBlockedMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, providers: [
512
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateRange), multi: true },
513
+ ], viewQueries: [{ propertyName: "prevSlot", first: true, predicate: ["prev"], descendants: true, isSignal: true }, { propertyName: "nextSlot", first: true, predicate: ["next"], descendants: true, isSignal: true }], ngImport: i0, template: `
514
+ <span #prev hidden><ng-content select="[tzPrev]" /></span>
515
+ <span #next hidden><ng-content select="[tzNext]" /></span>
516
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
517
+ }
518
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: DateRange, decorators: [{
519
+ type: Component,
520
+ args: [{
521
+ selector: 'tz-date-range',
522
+ standalone: true,
523
+ changeDetection: ChangeDetectionStrategy.OnPush,
524
+ providers: [
525
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateRange), multi: true },
526
+ ],
527
+ template: `
528
+ <span #prev hidden><ng-content select="[tzPrev]" /></span>
529
+ <span #next hidden><ng-content select="[tzNext]" /></span>
530
+ `,
531
+ }]
532
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], isDateDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDateDisabled", required: false }] }], today: [{ type: i0.Input, args: [{ isSignal: true, alias: "today", required: false }] }], blockAcrossDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "blockAcrossDisabled", required: false }] }], renderCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderCell", required: false }] }], rangeSpansBlockedMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "rangeSpansBlockedMessage", required: false }] }], prevSlot: [{ type: i0.ViewChild, args: ['prev', { isSignal: true }] }], nextSlot: [{ type: i0.ViewChild, args: ['next', { isSignal: true }] }] } });
533
+ /** Whatever was projected into a slot, or undefined so the default chevron stays. */
534
+ function projected(host, slot) {
535
+ const nodes = Array.from(slot.nativeElement.childNodes);
536
+ if (!nodes.some((n) => n.nodeType === Node.ELEMENT_NODE || n.textContent?.trim()))
537
+ return undefined;
538
+ const fragment = host.ownerDocument.createDocumentFragment();
539
+ fragment.append(...nodes);
540
+ return fragment;
541
+ }
542
+
543
+ const EMPTY$1 = { start: null, end: null };
544
+ /**
545
+ * `<tz-datetime-range>` — the interval from @tzslot/dom, spoken in Angular.
546
+ *
547
+ * The duration shown is the measured one, and when it disagrees with the clock
548
+ * faces the widget says so in words.
549
+ */
550
+ class DateTimeRange {
551
+ constructor() {
552
+ this.value = model(EMPTY$1, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
553
+ this.timeZone = input.required(...(ngDevMode ? [{ debugName: "timeZone" }] : /* istanbul ignore next */ []));
554
+ this.stepMinutes = input(30, ...(ngDevMode ? [{ debugName: "stepMinutes" }] : /* istanbul ignore next */ []));
555
+ this.minTime = input(undefined, ...(ngDevMode ? [{ debugName: "minTime" }] : /* istanbul ignore next */ []));
556
+ this.maxTime = input(undefined, ...(ngDevMode ? [{ debugName: "maxTime" }] : /* istanbul ignore next */ []));
557
+ this.isSlotDisabled = input(undefined, ...(ngDevMode ? [{ debugName: "isSlotDisabled" }] : /* istanbul ignore next */ []));
558
+ this.min = input(null, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
559
+ this.max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
560
+ this.locale = input(undefined, ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
561
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
562
+ this.startLabel = input(undefined, ...(ngDevMode ? [{ debugName: "startLabel" }] : /* istanbul ignore next */ []));
563
+ this.endLabel = input(undefined, ...(ngDevMode ? [{ debugName: "endLabel" }] : /* istanbul ignore next */ []));
564
+ this.endBeforeStartMessage = input(undefined, ...(ngDevMode ? [{ debugName: "endBeforeStartMessage" }] : /* istanbul ignore next */ []));
565
+ this.formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
566
+ this.messages = inject(TZSLOT_MESSAGES);
567
+ this.settings = computed(() => ({
568
+ value: this.value(),
569
+ timeZone: this.timeZone(),
570
+ stepMinutes: this.stepMinutes(),
571
+ minTime: this.minTime(),
572
+ maxTime: this.maxTime(),
573
+ isSlotDisabled: this.isSlotDisabled(),
574
+ min: this.min(),
575
+ max: this.max(),
576
+ locale: this.locale(),
577
+ disabled: this.disabled() || this.formDisabled(),
578
+ startLabel: this.startLabel(),
579
+ endLabel: this.endLabel(),
580
+ endBeforeStartMessage: this.endBeforeStartMessage(),
581
+ messages: this.messages,
582
+ }), ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
583
+ /** Created before the required timeZone is bound; the first change detection fills it in. */
584
+ this.range = createDateTimeRange(inject(ElementRef).nativeElement, {
585
+ messages: this.messages,
586
+ onChange: (next) => {
587
+ this.value.set(next);
588
+ this.onChange(next);
589
+ this.onTouched();
590
+ },
591
+ });
592
+ // ── ControlValueAccessor ────────────────────────────────────
593
+ this.onChange = () => { };
594
+ this.onTouched = () => { };
595
+ // The settings are read here, so the effect follows them; the call into the
596
+ // widget runs untracked. A widget may answer by calling back — closing a
597
+ // panel, say — and a callback that writes a signal inside an effect is an
598
+ // error on Angular 18 (NG0600), and a hidden dependency on any version.
599
+ effect(() => {
600
+ const settings = this.settings();
601
+ untracked(() => this.range.update(settings));
602
+ });
603
+ inject(DestroyRef).onDestroy(() => this.range.destroy());
604
+ }
605
+ /** Clears the selection and tells any form control about it. */
606
+ clear() {
607
+ this.range.clear();
608
+ }
609
+ writeValue(value) {
610
+ this.value.set(value ?? EMPTY$1);
611
+ }
612
+ registerOnChange(fn) {
613
+ this.onChange = fn;
614
+ }
615
+ registerOnTouched(fn) {
616
+ this.onTouched = fn;
617
+ }
618
+ setDisabledState(isDisabled) {
619
+ this.formDisabled.set(isDisabled);
620
+ }
621
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: DateTimeRange, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
622
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.23", type: DateTimeRange, isStandalone: true, selector: "tz-datetime-range", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, timeZone: { classPropertyName: "timeZone", publicName: "timeZone", isSignal: true, isRequired: true, transformFunction: null }, stepMinutes: { classPropertyName: "stepMinutes", publicName: "stepMinutes", isSignal: true, isRequired: false, transformFunction: null }, minTime: { classPropertyName: "minTime", publicName: "minTime", isSignal: true, isRequired: false, transformFunction: null }, maxTime: { classPropertyName: "maxTime", publicName: "maxTime", isSignal: true, isRequired: false, transformFunction: null }, isSlotDisabled: { classPropertyName: "isSlotDisabled", publicName: "isSlotDisabled", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, startLabel: { classPropertyName: "startLabel", publicName: "startLabel", isSignal: true, isRequired: false, transformFunction: null }, endLabel: { classPropertyName: "endLabel", publicName: "endLabel", isSignal: true, isRequired: false, transformFunction: null }, endBeforeStartMessage: { classPropertyName: "endBeforeStartMessage", publicName: "endBeforeStartMessage", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, providers: [
623
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateTimeRange), multi: true },
624
+ ], ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
625
+ }
626
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: DateTimeRange, decorators: [{
627
+ type: Component,
628
+ args: [{
629
+ selector: 'tz-datetime-range',
630
+ standalone: true,
631
+ changeDetection: ChangeDetectionStrategy.OnPush,
632
+ providers: [
633
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateTimeRange), multi: true },
634
+ ],
635
+ template: '',
636
+ }]
637
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], timeZone: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeZone", required: true }] }], stepMinutes: [{ type: i0.Input, args: [{ isSignal: true, alias: "stepMinutes", required: false }] }], minTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "minTime", required: false }] }], maxTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTime", required: false }] }], isSlotDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isSlotDisabled", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], startLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "startLabel", required: false }] }], endLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "endLabel", required: false }] }], endBeforeStartMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "endBeforeStartMessage", required: false }] }] } });
638
+
639
+ const EMPTY = { start: null, end: null, from: null, to: null };
640
+ /**
641
+ * `<tz-daily-range>` — a range of days with the same hours on each, from
642
+ * @tzslot/dom, spoken in Angular. "The 3rd to the 7th, 09:00 to 17:00."
643
+ */
644
+ class DailyRange {
645
+ constructor() {
646
+ this.value = model(EMPTY, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
647
+ /** An IANA identifier. The hours are read on the clocks of this zone. */
648
+ this.timeZone = input.required(...(ngDevMode ? [{ debugName: "timeZone" }] : /* istanbul ignore next */ []));
649
+ this.stepMinutes = input(30, ...(ngDevMode ? [{ debugName: "stepMinutes" }] : /* istanbul ignore next */ []));
650
+ /** The first and last times offered. */
651
+ this.minTime = input(undefined, ...(ngDevMode ? [{ debugName: "minTime" }] : /* istanbul ignore next */ []));
652
+ this.maxTime = input(undefined, ...(ngDevMode ? [{ debugName: "maxTime" }] : /* istanbul ignore next */ []));
653
+ this.firstDayOfWeek = input(1, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : /* istanbul ignore next */ []));
654
+ this.locale = input(undefined, ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
655
+ this.min = input(null, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
656
+ this.max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
657
+ this.isDateDisabled = input(undefined, ...(ngDevMode ? [{ debugName: "isDateDisabled" }] : /* istanbul ignore next */ []));
658
+ this.renderCell = input(undefined, ...(ngDevMode ? [{ debugName: "renderCell" }] : /* istanbul ignore next */ []));
659
+ this.today = input(Temporal.Now.plainDateISO(), ...(ngDevMode ? [{ debugName: "today" }] : /* istanbul ignore next */ []));
660
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
661
+ /** Every day's window and the real total, once all four parts are chosen. */
662
+ this.summary = signal(null, ...(ngDevMode ? [{ debugName: "summary" }] : /* istanbul ignore next */ []));
663
+ this.formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
664
+ this.messages = inject(TZSLOT_MESSAGES);
665
+ this.settings = computed(() => ({
666
+ value: this.value(),
667
+ timeZone: this.timeZone(),
668
+ stepMinutes: this.stepMinutes(),
669
+ minTime: this.minTime(),
670
+ maxTime: this.maxTime(),
671
+ firstDayOfWeek: this.firstDayOfWeek(),
672
+ locale: this.locale(),
673
+ min: this.min(),
674
+ max: this.max(),
675
+ isDateDisabled: this.isDateDisabled(),
676
+ renderCell: this.renderCell(),
677
+ today: this.today(),
678
+ disabled: this.disabled() || this.formDisabled(),
679
+ messages: this.messages,
680
+ }), ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
681
+ /** Created before the required timeZone is bound; the first change detection fills it in. */
682
+ this.range = createDailyRange(inject(ElementRef).nativeElement, {
683
+ messages: this.messages,
684
+ onChange: (next) => {
685
+ this.value.set(next);
686
+ this.onChange(next);
687
+ this.onTouched();
688
+ },
689
+ });
690
+ // ── ControlValueAccessor ────────────────────────────────────
691
+ this.onChange = () => { };
692
+ this.onTouched = () => { };
693
+ // The settings are read here, so the effect follows them; the call into the
694
+ // widget runs untracked. A widget may answer by calling back — closing a
695
+ // panel, say — and a callback that writes a signal inside an effect is an
696
+ // error on Angular 18 (NG0600), and a hidden dependency on any version.
697
+ effect(() => {
698
+ const settings = this.settings();
699
+ untracked(() => {
700
+ this.range.update(settings);
701
+ this.summary.set(this.range.summary);
702
+ });
703
+ });
704
+ inject(DestroyRef).onDestroy(() => this.range.destroy());
705
+ }
706
+ /** Clears all four parts and tells any form control about it. */
707
+ clear() {
708
+ this.range.clear();
709
+ }
710
+ writeValue(value) {
711
+ this.value.set(value ?? EMPTY);
712
+ }
713
+ registerOnChange(fn) {
714
+ this.onChange = fn;
715
+ }
716
+ registerOnTouched(fn) {
717
+ this.onTouched = fn;
718
+ }
719
+ setDisabledState(isDisabled) {
720
+ this.formDisabled.set(isDisabled);
721
+ }
722
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: DailyRange, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
723
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.23", type: DailyRange, isStandalone: true, selector: "tz-daily-range", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, timeZone: { classPropertyName: "timeZone", publicName: "timeZone", isSignal: true, isRequired: true, transformFunction: null }, stepMinutes: { classPropertyName: "stepMinutes", publicName: "stepMinutes", isSignal: true, isRequired: false, transformFunction: null }, minTime: { classPropertyName: "minTime", publicName: "minTime", isSignal: true, isRequired: false, transformFunction: null }, maxTime: { classPropertyName: "maxTime", publicName: "maxTime", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, isDateDisabled: { classPropertyName: "isDateDisabled", publicName: "isDateDisabled", isSignal: true, isRequired: false, transformFunction: null }, renderCell: { classPropertyName: "renderCell", publicName: "renderCell", isSignal: true, isRequired: false, transformFunction: null }, today: { classPropertyName: "today", publicName: "today", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, providers: [
724
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DailyRange), multi: true },
725
+ ], ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
726
+ }
727
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: DailyRange, decorators: [{
728
+ type: Component,
729
+ args: [{
730
+ selector: 'tz-daily-range',
731
+ standalone: true,
732
+ changeDetection: ChangeDetectionStrategy.OnPush,
733
+ providers: [
734
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DailyRange), multi: true },
735
+ ],
736
+ template: '',
737
+ }]
738
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], timeZone: [{ type: i0.Input, args: [{ isSignal: true, alias: "timeZone", required: true }] }], stepMinutes: [{ type: i0.Input, args: [{ isSignal: true, alias: "stepMinutes", required: false }] }], minTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "minTime", required: false }] }], maxTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTime", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], isDateDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDateDisabled", required: false }] }], renderCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderCell", required: false }] }], today: [{ type: i0.Input, args: [{ isSignal: true, alias: "today", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
739
+
740
+ /**
741
+ * `<tz-multi-date>` — several days, not necessarily next to each other, from
742
+ * @tzslot/dom, spoken in Angular. The value is always in date order.
743
+ */
744
+ class MultiDate {
745
+ constructor() {
746
+ /** The chosen days, in date order. Two-way: `[(value)]`. */
747
+ this.value = model([], ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
748
+ /** Once this many are chosen, the other days stop taking clicks. */
749
+ this.maxDates = input(undefined, ...(ngDevMode ? [{ debugName: "maxDates" }] : /* istanbul ignore next */ []));
750
+ this.firstDayOfWeek = input(1, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : /* istanbul ignore next */ []));
751
+ this.locale = input(undefined, ...(ngDevMode ? [{ debugName: "locale" }] : /* istanbul ignore next */ []));
752
+ this.min = input(null, ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
753
+ this.max = input(null, ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
754
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
755
+ this.isDateDisabled = input(undefined, ...(ngDevMode ? [{ debugName: "isDateDisabled" }] : /* istanbul ignore next */ []));
756
+ this.today = input(Temporal.Now.plainDateISO(), ...(ngDevMode ? [{ debugName: "today" }] : /* istanbul ignore next */ []));
757
+ this.view = model('days', ...(ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []));
758
+ this.renderCell = input(undefined, ...(ngDevMode ? [{ debugName: "renderCell" }] : /* istanbul ignore next */ []));
759
+ this.buttons = input([], ...(ngDevMode ? [{ debugName: "buttons" }] : /* istanbul ignore next */ []));
760
+ /** What the form control holds, each day as a Temporal date, a Date, or an ISO string. */
761
+ this.valueAs = input('temporal', ...(ngDevMode ? [{ debugName: "valueAs" }] : /* istanbul ignore next */ []));
762
+ /** The zone a Date is read in. Only consulted when valueAs is 'date'. */
763
+ this.valueTimeZone = input(Temporal.Now.timeZoneId(), ...(ngDevMode ? [{ debugName: "valueTimeZone" }] : /* istanbul ignore next */ []));
764
+ this.formDisabled = signal(false, ...(ngDevMode ? [{ debugName: "formDisabled" }] : /* istanbul ignore next */ []));
765
+ this.host = inject(ElementRef).nativeElement;
766
+ this.messages = inject(TZSLOT_MESSAGES);
767
+ this.prevSlot = viewChild.required('prev');
768
+ this.nextSlot = viewChild.required('next');
769
+ this.settings = computed(() => ({
770
+ value: this.value(),
771
+ maxDates: this.maxDates(),
772
+ view: this.view(),
773
+ firstDayOfWeek: this.firstDayOfWeek(),
774
+ locale: this.locale(),
775
+ min: this.min(),
776
+ max: this.max(),
777
+ disabled: this.disabled() || this.formDisabled(),
778
+ isDateDisabled: this.isDateDisabled(),
779
+ today: this.today(),
780
+ renderCell: this.renderCell(),
781
+ buttons: this.buttons(),
782
+ messages: this.messages,
783
+ }), ...(ngDevMode ? [{ debugName: "settings" }] : /* istanbul ignore next */ []));
784
+ this.calendar = createMultiDate(this.host, {
785
+ ...untracked(this.settings),
786
+ onChange: (dates) => {
787
+ this.value.set(dates);
788
+ this.onChange(dates);
789
+ this.onTouched();
790
+ },
791
+ onViewChange: (view) => this.view.set(view),
792
+ });
793
+ // ── ControlValueAccessor ────────────────────────────────────
794
+ this.onChange = () => { };
795
+ this.onTouched = () => { };
796
+ // The settings are read here, so the effect follows them; the call into the
797
+ // widget runs untracked. A widget may answer by calling back — closing a
798
+ // panel, say — and a callback that writes a signal inside an effect is an
799
+ // error on Angular 18 (NG0600), and a hidden dependency on any version.
800
+ effect(() => {
801
+ const settings = this.settings();
802
+ untracked(() => this.calendar.update(settings));
803
+ });
804
+ inject(DestroyRef).onDestroy(() => this.calendar.destroy());
805
+ }
806
+ ngAfterViewInit() {
807
+ const projected = (slot) => {
808
+ const nodes = Array.from(slot.nativeElement.childNodes);
809
+ if (!nodes.some((n) => n.nodeType === Node.ELEMENT_NODE || n.textContent?.trim()))
810
+ return undefined;
811
+ const fragment = this.host.ownerDocument.createDocumentFragment();
812
+ fragment.append(...nodes);
813
+ return fragment;
814
+ };
815
+ this.calendar.setIcons({ prev: projected(this.prevSlot()), next: projected(this.nextSlot()) });
816
+ }
817
+ /** Moves the grid without choosing anything. */
818
+ goTo(date) {
819
+ this.calendar.goTo({ year: date.year, month: date.month });
820
+ }
821
+ /** Empties the selection and tells any form control about it. */
822
+ clear() {
823
+ this.calendar.clear();
824
+ }
825
+ writeValue(value) {
826
+ const days = (value ?? []).map((d) => toPlainDate(d, this.valueTimeZone()));
827
+ this.value.set([...days].sort(Temporal.PlainDate.compare));
828
+ }
829
+ registerOnChange(fn) {
830
+ this.onChange = (dates) => fn(dates.map((d) => fromPlainDate(d, this.valueAs(), this.valueTimeZone())));
831
+ }
832
+ registerOnTouched(fn) {
833
+ this.onTouched = fn;
834
+ }
835
+ setDisabledState(isDisabled) {
836
+ this.formDisabled.set(isDisabled);
837
+ }
838
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: MultiDate, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
839
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.23", type: MultiDate, isStandalone: true, selector: "tz-multi-date", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, maxDates: { classPropertyName: "maxDates", publicName: "maxDates", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, isDateDisabled: { classPropertyName: "isDateDisabled", publicName: "isDateDisabled", isSignal: true, isRequired: false, transformFunction: null }, today: { classPropertyName: "today", publicName: "today", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null }, renderCell: { classPropertyName: "renderCell", publicName: "renderCell", isSignal: true, isRequired: false, transformFunction: null }, buttons: { classPropertyName: "buttons", publicName: "buttons", isSignal: true, isRequired: false, transformFunction: null }, valueAs: { classPropertyName: "valueAs", publicName: "valueAs", isSignal: true, isRequired: false, transformFunction: null }, valueTimeZone: { classPropertyName: "valueTimeZone", publicName: "valueTimeZone", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", view: "viewChange" }, providers: [
840
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MultiDate), multi: true },
841
+ ], viewQueries: [{ propertyName: "prevSlot", first: true, predicate: ["prev"], descendants: true, isSignal: true }, { propertyName: "nextSlot", first: true, predicate: ["next"], descendants: true, isSignal: true }], ngImport: i0, template: `
842
+ <span #prev hidden><ng-content select="[tzPrev]" /></span>
843
+ <span #next hidden><ng-content select="[tzNext]" /></span>
844
+ `, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
845
+ }
846
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: MultiDate, decorators: [{
847
+ type: Component,
848
+ args: [{
849
+ selector: 'tz-multi-date',
850
+ standalone: true,
851
+ changeDetection: ChangeDetectionStrategy.OnPush,
852
+ providers: [
853
+ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MultiDate), multi: true },
854
+ ],
855
+ template: `
856
+ <span #prev hidden><ng-content select="[tzPrev]" /></span>
857
+ <span #next hidden><ng-content select="[tzNext]" /></span>
858
+ `,
859
+ }]
860
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], maxDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDates", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], isDateDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDateDisabled", required: false }] }], today: [{ type: i0.Input, args: [{ isSignal: true, alias: "today", required: false }] }], view: [{ type: i0.Input, args: [{ isSignal: true, alias: "view", required: false }] }, { type: i0.Output, args: ["viewChange"] }], renderCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "renderCell", required: false }] }], buttons: [{ type: i0.Input, args: [{ isSignal: true, alias: "buttons", required: false }] }], valueAs: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueAs", required: false }] }], valueTimeZone: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueTimeZone", required: false }] }], prevSlot: [{ type: i0.ViewChild, args: ['prev', { isSignal: true }] }], nextSlot: [{ type: i0.ViewChild, args: ['next', { isSignal: true }] }] } });
861
+
862
+ /**
863
+ * @tzslot/ui — Angular components over the core.
864
+ *
865
+ * Angular CDK only; no Material, no design system. Structural class names and
866
+ * CSS custom properties (--tz-*), so a consumer restyles without fighting
867
+ * specificity.
868
+ */
869
+
870
+ /**
871
+ * Generated bundle index. Do not edit.
872
+ */
873
+
874
+ export { Calendar, DailyRange, DateField, DateRange, DateTimeRange, MultiDate, TZSLOT_MESSAGES, TimeSlotPicker, provideTzslotMessages };
875
+ //# sourceMappingURL=tzslot-angular.mjs.map