@egose/shadcn-theme-ng 0.5.3 → 0.6.1
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.
- package/README.md +131 -12
- package/autocomplete/fesm2022/autocomplete.mjs +14 -4
- package/autocomplete/types/autocomplete.d.ts +4 -1
- package/checkbox/README.md +6 -2
- package/checkbox/fesm2022/checkbox.mjs +11 -7
- package/checkbox/types/checkbox.d.ts +6 -4
- package/combobox/fesm2022/combobox.mjs +13 -7
- package/combobox/types/combobox.d.ts +8 -2
- package/data-table/README.md +174 -0
- package/data-table/fesm2022/data-table.mjs +713 -0
- package/data-table/package.json +25 -0
- package/data-table/types/data-table.d.ts +495 -0
- package/date-picker/README.md +41 -9
- package/date-picker/fesm2022/date-picker.mjs +265 -59
- package/date-picker/types/date-picker.d.ts +58 -27
- package/dropdown-menu/README.md +2 -0
- package/form-autocomplete/README.md +4 -2
- package/form-autocomplete/fesm2022/form-autocomplete.mjs +19 -6
- package/form-autocomplete/types/form-autocomplete.d.ts +9 -3
- package/form-combobox/README.md +4 -2
- package/form-combobox/fesm2022/form-combobox.mjs +23 -6
- package/form-combobox/types/form-combobox.d.ts +10 -3
- package/form-input-otp/README.md +7 -5
- package/form-input-otp/fesm2022/form-input-otp.mjs +20 -8
- package/form-input-otp/types/form-input-otp.d.ts +9 -3
- package/form-searchable-multiselect/README.md +15 -1
- package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +15 -3
- package/form-searchable-multiselect/types/form-searchable-multiselect.d.ts +9 -1
- package/form-slider/README.md +3 -1
- package/form-slider/fesm2022/form-slider.mjs +19 -6
- package/form-slider/types/form-slider.d.ts +9 -3
- package/form-text-input/fesm2022/form-text-input.mjs +1 -1
- package/form-textarea/fesm2022/form-textarea.mjs +1 -1
- package/form-toggle/README.md +22 -18
- package/form-toggle/fesm2022/form-toggle.mjs +22 -9
- package/form-toggle/types/form-toggle.d.ts +6 -2
- package/input/README.md +7 -12
- package/input/fesm2022/input.mjs +7 -4
- package/input/types/input.d.ts +3 -1
- package/input-otp/README.md +33 -9
- package/input-otp/fesm2022/input-otp.mjs +127 -11
- package/input-otp/types/input-otp.d.ts +24 -4
- package/layout-simple/fesm2022/layout-simple.mjs +1 -1
- package/package.json +6 -1
- package/pagination/README.md +21 -12
- package/pagination/fesm2022/pagination.mjs +73 -65
- package/pagination/types/pagination.d.ts +21 -8
- package/phone-input/README.md +16 -0
- package/phone-input/fesm2022/phone-input.mjs +42 -4
- package/phone-input/types/phone-input.d.ts +5 -2
- package/searchable-multiselect/README.md +62 -40
- package/searchable-multiselect/fesm2022/searchable-multiselect.mjs +59 -32
- package/searchable-multiselect/types/searchable-multiselect.d.ts +23 -6
- package/slider/fesm2022/slider.mjs +9 -5
- package/slider/types/slider.d.ts +6 -2
- package/stepper/README.md +39 -19
- package/stepper/fesm2022/stepper.mjs +64 -12
- package/stepper/types/stepper.d.ts +12 -1
- package/table/README.md +2 -0
- package/table/fesm2022/table.mjs +12 -8
- package/table/types/table.d.ts +7 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, input, booleanAttribute, computed, ChangeDetectionStrategy, Component, forwardRef, viewChild, contentChild,
|
|
2
|
+
import { InjectionToken, inject, signal, Injectable, linkedSignal, Directive, input, booleanAttribute, computed, ChangeDetectionStrategy, Component, forwardRef, viewChild, contentChild, output, ElementRef, effect, numberAttribute, untracked, NgModule } from '@angular/core';
|
|
3
3
|
import { NgIcon, provideIcons } from '@ng-icons/core';
|
|
4
4
|
import { lucideX, lucideCalendar, lucideChevronDown } from '@ng-icons/lucide';
|
|
5
5
|
import { BrnDateInput, provideBrnDatePickerTrigger, BrnDatePickerTriggerToken, provideBrnDatePicker, injectBrnDatePicker } from '@spartan-ng/brain/date-picker';
|
|
@@ -10,6 +10,8 @@ import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
|
10
10
|
import * as i1$1 from '@spartan-ng/brain/field';
|
|
11
11
|
import { provideBrnLabelable, BrnFieldControl, BrnFieldControlDescribedBy } from '@spartan-ng/brain/field';
|
|
12
12
|
import { BrnPopover } from '@spartan-ng/brain/popover';
|
|
13
|
+
import { injectDateAdapter } from '@spartan-ng/brain/date-time';
|
|
14
|
+
import { BrnCalendar, BrnCalendarMulti, BrnCalendarRange } from '@spartan-ng/brain/calendar';
|
|
13
15
|
import * as i3 from '@egose/shadcn-theme-ng/calendar';
|
|
14
16
|
import { HlmCalendar, HlmCalendarMulti, HlmCalendarRange, HlmCalendarImports } from '@egose/shadcn-theme-ng/calendar';
|
|
15
17
|
import * as i2 from '@egose/shadcn-theme-ng/popover';
|
|
@@ -68,7 +70,100 @@ function injectHlmDatePickerMultiConfig() {
|
|
|
68
70
|
return injectedConfig ? injectedConfig : getDefaultConfig$3();
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
|
|
73
|
+
/** Internal synchronization for explicit writes, including writes of the same value. */
|
|
74
|
+
class HlmDatePickerCommitState {
|
|
75
|
+
revision = signal(0, /* @ts-ignore */
|
|
76
|
+
...(ngDevMode ? [{ debugName: "revision" }] : /* istanbul ignore next */ []));
|
|
77
|
+
changed() {
|
|
78
|
+
this.revision.update((revision) => revision + 1);
|
|
79
|
+
}
|
|
80
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDatePickerCommitState, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
81
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDatePickerCommitState });
|
|
82
|
+
}
|
|
83
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDatePickerCommitState, decorators: [{
|
|
84
|
+
type: Injectable
|
|
85
|
+
}] });
|
|
86
|
+
/** Match the calendar's inclusive whole-day bounds with the configured adapter. */
|
|
87
|
+
function isSelectableDate(adapter, value, min, max) {
|
|
88
|
+
return (value != null &&
|
|
89
|
+
Number.isFinite(adapter.getTime(value)) &&
|
|
90
|
+
(min == null || !adapter.isBefore(value, adapter.startOfDay(min))) &&
|
|
91
|
+
(max == null || !adapter.isAfter(value, adapter.endOfDay(max))));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Internal input lifecycle shared by the single, range and multi pickers. */
|
|
95
|
+
class HlmConstrainedDateInput extends BrnDateInput {
|
|
96
|
+
_commitState = inject(HlmDatePickerCommitState);
|
|
97
|
+
_inputValue = linkedSignal({ ...(ngDevMode ? { debugName: "_inputValue" } : /* istanbul ignore next */ {}), source: () => ({
|
|
98
|
+
revision: this._commitState.revision(),
|
|
99
|
+
formatted: this._datePicker.formattedDate(),
|
|
100
|
+
value: this._datePicker.value?.(),
|
|
101
|
+
inputValue: this.inputValue(),
|
|
102
|
+
}),
|
|
103
|
+
computation: (source, previous) => {
|
|
104
|
+
if (!previous)
|
|
105
|
+
return source.formatted ?? source.inputValue;
|
|
106
|
+
if (source.revision !== previous.source.revision ||
|
|
107
|
+
source.value !== previous.source.value ||
|
|
108
|
+
source.formatted !== previous.source.formatted)
|
|
109
|
+
return source.formatted ?? '';
|
|
110
|
+
if (source.inputValue !== previous.source.inputValue)
|
|
111
|
+
return source.inputValue;
|
|
112
|
+
return previous.value;
|
|
113
|
+
} });
|
|
114
|
+
/** Rejected text stays invalid until a successful commit, clear, or external value write. */
|
|
115
|
+
inputInvalid = linkedSignal(() => {
|
|
116
|
+
this._commitState.revision();
|
|
117
|
+
this._datePicker.value?.();
|
|
118
|
+
this.inputValue();
|
|
119
|
+
return false;
|
|
120
|
+
}, /* @ts-ignore */
|
|
121
|
+
...(ngDevMode ? [{ debugName: "inputInvalid" }] : /* istanbul ignore next */ []));
|
|
122
|
+
_commitDate() {
|
|
123
|
+
if (this._disabled() || this.readonly())
|
|
124
|
+
return;
|
|
125
|
+
const text = this._inputValue();
|
|
126
|
+
const parsed = text ? this.parseValue(text) : null;
|
|
127
|
+
const picker = this._datePicker;
|
|
128
|
+
const accepted = (!text || parsed != null) && picker.updateDate(parsed);
|
|
129
|
+
this.inputInvalid.set(!accepted);
|
|
130
|
+
this._datePicker.touched?.();
|
|
131
|
+
}
|
|
132
|
+
_handleBlur() {
|
|
133
|
+
if (this._disabled() || this.readonly())
|
|
134
|
+
return;
|
|
135
|
+
this._commitDate();
|
|
136
|
+
if (!this.inputInvalid())
|
|
137
|
+
this._inputValue.set(this._datePicker.formattedDate() ?? '');
|
|
138
|
+
}
|
|
139
|
+
_handleEnter(event) {
|
|
140
|
+
event.preventDefault();
|
|
141
|
+
if (this._disabled() || this.readonly())
|
|
142
|
+
return;
|
|
143
|
+
this._commitDate();
|
|
144
|
+
if (!this.inputInvalid()) {
|
|
145
|
+
this._popover().close();
|
|
146
|
+
this._handleFocus();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
_handleFocus() {
|
|
150
|
+
if (!this.inputInvalid())
|
|
151
|
+
super._handleFocus();
|
|
152
|
+
}
|
|
153
|
+
_clear() {
|
|
154
|
+
if (this._disabled() || this.readonly())
|
|
155
|
+
return;
|
|
156
|
+
this._inputValue.set('');
|
|
157
|
+
this._commitDate();
|
|
158
|
+
}
|
|
159
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmConstrainedDateInput, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
160
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.3", type: HlmConstrainedDateInput, isStandalone: true, usesInheritance: true, ngImport: i0 });
|
|
161
|
+
}
|
|
162
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmConstrainedDateInput, decorators: [{
|
|
163
|
+
type: Directive
|
|
164
|
+
}] });
|
|
165
|
+
|
|
166
|
+
class HlmDateMultiInput extends HlmConstrainedDateInput {
|
|
72
167
|
_config = injectHlmDatePickerMultiConfig();
|
|
73
168
|
/** Native `name` attribute forwarded to the inner `<input>`. */
|
|
74
169
|
name = input(undefined, /* @ts-ignore */
|
|
@@ -91,9 +186,9 @@ class HlmDateMultiInput extends BrnDateInput {
|
|
|
91
186
|
classes(() => [this.userClass()]);
|
|
92
187
|
}
|
|
93
188
|
/**
|
|
94
|
-
* Parses input text into dates. Return `null` for invalid input
|
|
95
|
-
*
|
|
96
|
-
*
|
|
189
|
+
* Parses input text into dates. Return `null` for invalid input. Rejected
|
|
190
|
+
* text stays editable and aria-invalid; the committed value is preserved.
|
|
191
|
+
* Empty text explicitly clears on blur/Enter.
|
|
97
192
|
*
|
|
98
193
|
* Defaults to `parseDate` from `HlmDatePickerMultiConfig`.
|
|
99
194
|
*/
|
|
@@ -126,7 +221,8 @@ class HlmDateMultiInput extends BrnDateInput {
|
|
|
126
221
|
[placeholder]="placeholder()"
|
|
127
222
|
[readonly]="readonly()"
|
|
128
223
|
[disabled]="_disabled()"
|
|
129
|
-
[
|
|
224
|
+
[attr.aria-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
|
|
225
|
+
[attr.data-matches-spartan-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
|
|
130
226
|
[class]="$inputClass()"
|
|
131
227
|
(click)="_handleClick()"
|
|
132
228
|
(keydown.arrowDown)="_open()"
|
|
@@ -180,7 +276,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
180
276
|
[placeholder]="placeholder()"
|
|
181
277
|
[readonly]="readonly()"
|
|
182
278
|
[disabled]="_disabled()"
|
|
183
|
-
[
|
|
279
|
+
[attr.aria-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
|
|
280
|
+
[attr.data-matches-spartan-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
|
|
184
281
|
[class]="$inputClass()"
|
|
185
282
|
(click)="_handleClick()"
|
|
186
283
|
(keydown.arrowDown)="_open()"
|
|
@@ -244,6 +341,11 @@ const HLM_DATE_PICKER_VALUE_ACCESSOR = {
|
|
|
244
341
|
};
|
|
245
342
|
class HlmDatePicker {
|
|
246
343
|
_config = injectHlmDatePickerConfig();
|
|
344
|
+
_dateAdapter = injectDateAdapter();
|
|
345
|
+
_commitState = inject(HlmDatePickerCommitState);
|
|
346
|
+
_calendar = viewChild((BrnCalendar), /* @ts-ignore */
|
|
347
|
+
...(ngDevMode ? [{ debugName: "_calendar" }] : /* istanbul ignore next */ []));
|
|
348
|
+
_restoringCalendar = false;
|
|
247
349
|
popover = viewChild.required(BrnPopover, /* @ts-ignore */
|
|
248
350
|
...(ngDevMode ? [{ debugName: "popover" }] : /* istanbul ignore next */ []));
|
|
249
351
|
_trigger = contentChild(BrnDatePickerTriggerToken, /* @ts-ignore */
|
|
@@ -305,30 +407,46 @@ class HlmDatePicker {
|
|
|
305
407
|
this._onTouched?.();
|
|
306
408
|
}
|
|
307
409
|
_handleChange(value) {
|
|
308
|
-
if (this.
|
|
410
|
+
if (this._restoringCalendar)
|
|
309
411
|
return;
|
|
310
|
-
this.updateDate(value ?? null)
|
|
412
|
+
if (!this.updateDate(value ?? null)) {
|
|
413
|
+
// Brain model signals have already changed before their output fires.
|
|
414
|
+
this._restoringCalendar = true;
|
|
415
|
+
try {
|
|
416
|
+
this._calendar()?.date.set(this._mutableDate());
|
|
417
|
+
}
|
|
418
|
+
finally {
|
|
419
|
+
this._restoringCalendar = false;
|
|
420
|
+
}
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
311
423
|
if (this.autoCloseOnSelect()) {
|
|
312
424
|
this._popoverState.set('closed');
|
|
313
425
|
}
|
|
314
426
|
}
|
|
315
427
|
/**
|
|
316
|
-
* Commit a
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
* is parsing user-entered values while typing.
|
|
428
|
+
* Commit a user value (null clears). Returns false without changing/emitting
|
|
429
|
+
* the model when disabled or when the raw/transformed date is invalid or
|
|
430
|
+
* outside the adapter's inclusive whole-day min/max bounds.
|
|
320
431
|
*/
|
|
321
432
|
updateDate(value) {
|
|
322
433
|
if (this.disabledState())
|
|
323
|
-
return;
|
|
434
|
+
return false;
|
|
435
|
+
if (value != null && !isSelectableDate(this._dateAdapter, value, this.min(), this.max()))
|
|
436
|
+
return false;
|
|
324
437
|
const transformedDate = value != null ? this.transformDate()(value) : undefined;
|
|
438
|
+
if (value != null && !isSelectableDate(this._dateAdapter, transformedDate, this.min(), this.max()))
|
|
439
|
+
return false;
|
|
325
440
|
this._mutableDate.set(transformedDate);
|
|
441
|
+
this._commitState.changed();
|
|
326
442
|
this._onChange?.(transformedDate ?? null);
|
|
327
443
|
this.dateChange.emit(transformedDate ?? null);
|
|
444
|
+
return true;
|
|
328
445
|
}
|
|
329
|
-
/**
|
|
446
|
+
/** Programmatic CVA write: transforms without enforcing user constraints or emitting. Clears rejected text. */
|
|
330
447
|
writeValue(value) {
|
|
331
|
-
this._mutableDate.set(value ? this.transformDate()(value) : undefined);
|
|
448
|
+
this._mutableDate.set(value != null ? this.transformDate()(value) : undefined);
|
|
449
|
+
this._commitState.changed();
|
|
332
450
|
}
|
|
333
451
|
registerOnChange(fn) {
|
|
334
452
|
this._onChange = fn;
|
|
@@ -350,24 +468,35 @@ class HlmDatePicker {
|
|
|
350
468
|
}
|
|
351
469
|
reset() {
|
|
352
470
|
this._mutableDate.set(undefined);
|
|
471
|
+
this._commitState.changed();
|
|
353
472
|
this._onChange?.(null);
|
|
354
473
|
this.dateChange.emit(null);
|
|
355
474
|
}
|
|
356
475
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDatePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
357
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.3", type: HlmDatePicker, isStandalone: true, selector: "hlm-date-picker", inputs: { captionLayout: { classPropertyName: "captionLayout", publicName: "captionLayout", 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 }, wrapperDisabled: { classPropertyName: "wrapperDisabled", publicName: "wrapperDisabled", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, defaultFocusedDate: { classPropertyName: "defaultFocusedDate", publicName: "defaultFocusedDate", isSignal: true, isRequired: false, transformFunction: null }, autoCloseOnSelect: { classPropertyName: "autoCloseOnSelect", publicName: "autoCloseOnSelect", isSignal: true, isRequired: false, transformFunction: null }, formatDate: { classPropertyName: "formatDate", publicName: "formatDate", isSignal: true, isRequired: false, transformFunction: null }, transformDate: { classPropertyName: "transformDate", publicName: "transformDate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, host: { classAttribute: "block w-full min-w-0 max-w-full" }, providers: [
|
|
476
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.3", type: HlmDatePicker, isStandalone: true, selector: "hlm-date-picker", inputs: { captionLayout: { classPropertyName: "captionLayout", publicName: "captionLayout", 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 }, wrapperDisabled: { classPropertyName: "wrapperDisabled", publicName: "wrapperDisabled", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, defaultFocusedDate: { classPropertyName: "defaultFocusedDate", publicName: "defaultFocusedDate", isSignal: true, isRequired: false, transformFunction: null }, autoCloseOnSelect: { classPropertyName: "autoCloseOnSelect", publicName: "autoCloseOnSelect", isSignal: true, isRequired: false, transformFunction: null }, formatDate: { classPropertyName: "formatDate", publicName: "formatDate", isSignal: true, isRequired: false, transformFunction: null }, transformDate: { classPropertyName: "transformDate", publicName: "transformDate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, host: { classAttribute: "block w-full min-w-0 max-w-full" }, providers: [
|
|
477
|
+
HlmDatePickerCommitState,
|
|
478
|
+
HLM_DATE_PICKER_VALUE_ACCESSOR,
|
|
479
|
+
provideBrnDatePicker(HlmDatePicker),
|
|
480
|
+
provideBrnLabelable(HlmDatePicker),
|
|
481
|
+
], queries: [{ propertyName: "_trigger", first: true, predicate: BrnDatePickerTriggerToken, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_calendar", first: true, predicate: (BrnCalendar), descendants: true, isSignal: true }, { propertyName: "popover", first: true, predicate: BrnPopover, descendants: true, isSignal: true }], hostDirectives: [{ directive: i1$1.BrnFieldControl }], ngImport: i0, template: "\n <hlm-popover sideOffset=\"5\" [state]=\"_popoverState()\" (stateChanged)=\"_onStateChange($event)\">\n <ng-content />\n\n <hlm-popover-content class=\"w-fit p-0\" *hlmPopoverPortal=\"let ctx\">\n <ng-content select=\"[hlmDatePickerHeader]\" />\n <hlm-calendar\n class=\"rounded-none border-0\"\n [captionLayout]=\"captionLayout()\"\n [date]=\"_mutableDate()\"\n [defaultFocusedDate]=\"_mutableDate() ?? defaultFocusedDate()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [disabled]=\"disabledState()\"\n (dateChange)=\"_handleChange($event)\"\n />\n <ng-content select=\"[hlmDatePickerFooter]\" />\n </hlm-popover-content>\n </hlm-popover>\n ", isInline: true, dependencies: [{ kind: "directive", type: i2.HlmPopover, selector: "[hlmPopover],hlm-popover" }, { kind: "directive", type: i2.HlmPopoverContent, selector: "[hlmPopoverContent],hlm-popover-content" }, { kind: "directive", type: i2.HlmPopoverPortal, selector: "[hlmPopoverPortal]" }, { kind: "component", type: HlmCalendar, selector: "hlm-calendar", inputs: ["captionLayout"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
358
482
|
}
|
|
359
483
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDatePicker, decorators: [{
|
|
360
484
|
type: Component,
|
|
361
485
|
args: [{
|
|
362
486
|
selector: 'hlm-date-picker',
|
|
363
487
|
imports: [HlmPopoverImports, HlmCalendar],
|
|
364
|
-
providers: [
|
|
488
|
+
providers: [
|
|
489
|
+
HlmDatePickerCommitState,
|
|
490
|
+
HLM_DATE_PICKER_VALUE_ACCESSOR,
|
|
491
|
+
provideBrnDatePicker(HlmDatePicker),
|
|
492
|
+
provideBrnLabelable(HlmDatePicker),
|
|
493
|
+
],
|
|
365
494
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
366
495
|
hostDirectives: [BrnFieldControl],
|
|
367
496
|
host: { class: "block w-full min-w-0 max-w-full" },
|
|
368
497
|
template: "\n <hlm-popover sideOffset=\"5\" [state]=\"_popoverState()\" (stateChanged)=\"_onStateChange($event)\">\n <ng-content />\n\n <hlm-popover-content class=\"w-fit p-0\" *hlmPopoverPortal=\"let ctx\">\n <ng-content select=\"[hlmDatePickerHeader]\" />\n <hlm-calendar\n class=\"rounded-none border-0\"\n [captionLayout]=\"captionLayout()\"\n [date]=\"_mutableDate()\"\n [defaultFocusedDate]=\"_mutableDate() ?? defaultFocusedDate()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [disabled]=\"disabledState()\"\n (dateChange)=\"_handleChange($event)\"\n />\n <ng-content select=\"[hlmDatePickerFooter]\" />\n </hlm-popover-content>\n </hlm-popover>\n ",
|
|
369
498
|
}]
|
|
370
|
-
}], propDecorators: { popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnPopover), { isSignal: true }] }], _trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BrnDatePickerTriggerToken), { isSignal: true }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", 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 }] }], wrapperDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrapperDisabled", required: false }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }], defaultFocusedDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultFocusedDate", required: false }] }], autoCloseOnSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCloseOnSelect", required: false }] }], formatDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatDate", required: false }] }], transformDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformDate", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
|
|
499
|
+
}], propDecorators: { _calendar: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnCalendar), { isSignal: true }] }], popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnPopover), { isSignal: true }] }], _trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BrnDatePickerTriggerToken), { isSignal: true }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", 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 }] }], wrapperDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrapperDisabled", required: false }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }], defaultFocusedDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultFocusedDate", required: false }] }], autoCloseOnSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCloseOnSelect", required: false }] }], formatDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatDate", required: false }] }], transformDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformDate", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
|
|
371
500
|
|
|
372
501
|
class HlmDatePickerAnchor {
|
|
373
502
|
_host = inject(ElementRef, { host: true });
|
|
@@ -389,7 +518,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
389
518
|
args: [{ selector: '[hlmDatePickerAnchor]' }]
|
|
390
519
|
}], ctorParameters: () => [], propDecorators: { hlmDatePickerAnchorForInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "hlmDatePickerAnchorFor", required: false }] }] } });
|
|
391
520
|
|
|
392
|
-
class HlmDatePickerInput extends
|
|
521
|
+
class HlmDatePickerInput extends HlmConstrainedDateInput {
|
|
393
522
|
_config = injectHlmDatePickerConfig();
|
|
394
523
|
ariaLabel = input(undefined, /* @ts-ignore */
|
|
395
524
|
...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
@@ -413,8 +542,8 @@ class HlmDatePickerInput extends BrnDateInput {
|
|
|
413
542
|
}
|
|
414
543
|
/**
|
|
415
544
|
* Parses input text into a date value. Return `null` for invalid
|
|
416
|
-
* input
|
|
417
|
-
*
|
|
545
|
+
* input. Rejected text stays editable and aria-invalid; the committed value
|
|
546
|
+
* is preserved. Empty text explicitly clears on blur/Enter.
|
|
418
547
|
*
|
|
419
548
|
* Defaults to `parseDate` from `HlmDatePickerConfig`.
|
|
420
549
|
*/
|
|
@@ -447,7 +576,8 @@ class HlmDatePickerInput extends BrnDateInput {
|
|
|
447
576
|
[placeholder]="placeholder()"
|
|
448
577
|
[readonly]="readonly()"
|
|
449
578
|
[disabled]="_disabled()"
|
|
450
|
-
[
|
|
579
|
+
[attr.aria-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
|
|
580
|
+
[attr.data-matches-spartan-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
|
|
451
581
|
[class]="$inputClass()"
|
|
452
582
|
(click)="_handleClick()"
|
|
453
583
|
(keydown.arrowDown)="_open()"
|
|
@@ -501,7 +631,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
501
631
|
[placeholder]="placeholder()"
|
|
502
632
|
[readonly]="readonly()"
|
|
503
633
|
[disabled]="_disabled()"
|
|
504
|
-
[
|
|
634
|
+
[attr.aria-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
|
|
635
|
+
[attr.data-matches-spartan-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
|
|
505
636
|
[class]="$inputClass()"
|
|
506
637
|
(click)="_handleClick()"
|
|
507
638
|
(keydown.arrowDown)="_open()"
|
|
@@ -544,6 +675,11 @@ const HLM_DATE_PICKER_MUTLI_VALUE_ACCESSOR = {
|
|
|
544
675
|
};
|
|
545
676
|
class HlmDatePickerMulti {
|
|
546
677
|
_config = injectHlmDatePickerMultiConfig();
|
|
678
|
+
_dateAdapter = injectDateAdapter();
|
|
679
|
+
_commitState = inject(HlmDatePickerCommitState);
|
|
680
|
+
_calendar = viewChild((BrnCalendarMulti), /* @ts-ignore */
|
|
681
|
+
...(ngDevMode ? [{ debugName: "_calendar" }] : /* istanbul ignore next */ []));
|
|
682
|
+
_restoringCalendar = false;
|
|
547
683
|
popover = viewChild.required(BrnPopover, /* @ts-ignore */
|
|
548
684
|
...(ngDevMode ? [{ debugName: "popover" }] : /* istanbul ignore next */ []));
|
|
549
685
|
_trigger = contentChild(BrnDatePickerTriggerToken, /* @ts-ignore */
|
|
@@ -557,7 +693,7 @@ class HlmDatePickerMulti {
|
|
|
557
693
|
/** The maximum date that can be selected. */
|
|
558
694
|
max = input(/* @ts-ignore */
|
|
559
695
|
...(ngDevMode ? [undefined, { debugName: "max" }] : /* istanbul ignore next */ []));
|
|
560
|
-
/**
|
|
696
|
+
/** Deselection floor; selection can grow from empty below this count. Explicit clear is allowed. */
|
|
561
697
|
minSelection = input(undefined, { ...(ngDevMode ? { debugName: "minSelection" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
562
698
|
/** The maximum selectable dates. */
|
|
563
699
|
maxSelection = input(undefined, { ...(ngDevMode ? { debugName: "maxSelection" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
@@ -605,37 +741,58 @@ class HlmDatePickerMulti {
|
|
|
605
741
|
this._onTouched?.();
|
|
606
742
|
}
|
|
607
743
|
_handleChange(value) {
|
|
608
|
-
if (value === undefined)
|
|
744
|
+
if (this._restoringCalendar || value === undefined)
|
|
609
745
|
return;
|
|
610
|
-
if (this.
|
|
746
|
+
if (!this.updateDate(value)) {
|
|
747
|
+
// Restore the calendar's already-mutated model without a second user commit.
|
|
748
|
+
this._restoringCalendar = true;
|
|
749
|
+
try {
|
|
750
|
+
this._calendar()?.date.set(this._mutableDate());
|
|
751
|
+
}
|
|
752
|
+
finally {
|
|
753
|
+
this._restoringCalendar = false;
|
|
754
|
+
}
|
|
611
755
|
return;
|
|
612
|
-
|
|
613
|
-
this._mutableDate.set(transformedDate);
|
|
614
|
-
this._onChange?.(transformedDate);
|
|
615
|
-
this.dateChange.emit(transformedDate);
|
|
756
|
+
}
|
|
616
757
|
if (this.autoCloseOnMaxSelection() && this._mutableDate()?.length === this.maxSelection()) {
|
|
617
758
|
this._popoverState.set('closed');
|
|
618
759
|
}
|
|
619
760
|
}
|
|
620
761
|
/**
|
|
621
|
-
* Commit dates
|
|
622
|
-
*
|
|
623
|
-
*
|
|
762
|
+
* Commit user dates, validating raw and transformed dates/counts. Returns
|
|
763
|
+
* false without changing/emitting on rejection. Min selection prevents
|
|
764
|
+
* reductions below the floor, but permits growth from empty. Null explicitly
|
|
765
|
+
* clears (emits []), bypassing the selection floor and transform.
|
|
624
766
|
*/
|
|
625
767
|
updateDate(value) {
|
|
626
768
|
if (this._disabled())
|
|
627
|
-
return;
|
|
769
|
+
return false;
|
|
770
|
+
if (value && !this._isSelectionAllowed(value))
|
|
771
|
+
return false;
|
|
628
772
|
const transformedDate = value ? this.transformDates()(value) : undefined;
|
|
773
|
+
if (value && (!transformedDate || !this._isSelectionAllowed(transformedDate)))
|
|
774
|
+
return false;
|
|
629
775
|
this._mutableDate.set(transformedDate);
|
|
776
|
+
this._commitState.changed();
|
|
630
777
|
this._onChange?.(transformedDate ?? []);
|
|
631
778
|
this.dateChange.emit(transformedDate ?? []);
|
|
779
|
+
return true;
|
|
780
|
+
}
|
|
781
|
+
_isSelectionAllowed(dates) {
|
|
782
|
+
const min = this.minSelection();
|
|
783
|
+
const max = this.maxSelection();
|
|
784
|
+
const currentCount = this._mutableDate()?.length ?? 0;
|
|
785
|
+
return (!(max != null && dates.length > max) &&
|
|
786
|
+
!(min != null && dates.length < min && dates.length < currentCount) &&
|
|
787
|
+
dates.every((date) => isSelectableDate(this._dateAdapter, date, this.min(), this.max())));
|
|
632
788
|
}
|
|
633
789
|
touched() {
|
|
634
790
|
this._onTouched?.();
|
|
635
791
|
}
|
|
636
|
-
/**
|
|
792
|
+
/** Programmatic CVA write: transforms without enforcing user constraints or emitting. Clears rejected text. */
|
|
637
793
|
writeValue(value) {
|
|
638
794
|
this._mutableDate.set(value ? this.transformDates()(value) : undefined);
|
|
795
|
+
this._commitState.changed();
|
|
639
796
|
}
|
|
640
797
|
registerOnChange(fn) {
|
|
641
798
|
this._onChange = fn;
|
|
@@ -654,15 +811,17 @@ class HlmDatePickerMulti {
|
|
|
654
811
|
}
|
|
655
812
|
reset() {
|
|
656
813
|
this._mutableDate.set(undefined);
|
|
814
|
+
this._commitState.changed();
|
|
657
815
|
this._onChange?.([]);
|
|
658
816
|
this.dateChange.emit([]);
|
|
659
817
|
}
|
|
660
818
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDatePickerMulti, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
661
819
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.3", type: HlmDatePickerMulti, isStandalone: true, selector: "hlm-date-picker-multi", inputs: { captionLayout: { classPropertyName: "captionLayout", publicName: "captionLayout", 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 }, minSelection: { classPropertyName: "minSelection", publicName: "minSelection", isSignal: true, isRequired: false, transformFunction: null }, maxSelection: { classPropertyName: "maxSelection", publicName: "maxSelection", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, autoCloseOnMaxSelection: { classPropertyName: "autoCloseOnMaxSelection", publicName: "autoCloseOnMaxSelection", isSignal: true, isRequired: false, transformFunction: null }, formatDates: { classPropertyName: "formatDates", publicName: "formatDates", isSignal: true, isRequired: false, transformFunction: null }, transformDates: { classPropertyName: "transformDates", publicName: "transformDates", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, host: { classAttribute: "block" }, providers: [
|
|
820
|
+
HlmDatePickerCommitState,
|
|
662
821
|
HLM_DATE_PICKER_MUTLI_VALUE_ACCESSOR,
|
|
663
822
|
provideBrnDatePicker(HlmDatePickerMulti),
|
|
664
823
|
provideBrnLabelable(HlmDatePickerMulti),
|
|
665
|
-
], queries: [{ propertyName: "_trigger", first: true, predicate: BrnDatePickerTriggerToken, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "popover", first: true, predicate: BrnPopover, descendants: true, isSignal: true }], hostDirectives: [{ directive: i1$1.BrnFieldControl }], ngImport: i0, template: "\n <hlm-popover sideOffset=\"5\" [state]=\"_popoverState()\" (stateChanged)=\"_onStateChange($event)\">\n <ng-content />\n\n <hlm-popover-content class=\"w-fit p-0\" *hlmPopoverPortal=\"let ctx\">\n <ng-content select=\"[hlmDatePickerHeader]\" />\n <hlm-calendar-multi\n class=\"rounded-none border-0\"\n [date]=\"_mutableDate()\"\n [captionLayout]=\"captionLayout()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [minSelection]=\"minSelection()\"\n [maxSelection]=\"maxSelection()\"\n [disabled]=\"_disabled()\"\n (dateChange)=\"_handleChange($event)\"\n />\n <ng-content select=\"[hlmDatePickerFooter]\" />\n </hlm-popover-content>\n </hlm-popover>\n ", isInline: true, dependencies: [{ kind: "directive", type: i2.HlmPopover, selector: "[hlmPopover],hlm-popover" }, { kind: "directive", type: i2.HlmPopoverContent, selector: "[hlmPopoverContent],hlm-popover-content" }, { kind: "directive", type: i2.HlmPopoverPortal, selector: "[hlmPopoverPortal]" }, { kind: "component", type: HlmCalendarMulti, selector: "hlm-calendar-multi", inputs: ["captionLayout"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
824
|
+
], queries: [{ propertyName: "_trigger", first: true, predicate: BrnDatePickerTriggerToken, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_calendar", first: true, predicate: (BrnCalendarMulti), descendants: true, isSignal: true }, { propertyName: "popover", first: true, predicate: BrnPopover, descendants: true, isSignal: true }], hostDirectives: [{ directive: i1$1.BrnFieldControl }], ngImport: i0, template: "\n <hlm-popover sideOffset=\"5\" [state]=\"_popoverState()\" (stateChanged)=\"_onStateChange($event)\">\n <ng-content />\n\n <hlm-popover-content class=\"w-fit p-0\" *hlmPopoverPortal=\"let ctx\">\n <ng-content select=\"[hlmDatePickerHeader]\" />\n <hlm-calendar-multi\n class=\"rounded-none border-0\"\n [date]=\"_mutableDate()\"\n [captionLayout]=\"captionLayout()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [minSelection]=\"minSelection()\"\n [maxSelection]=\"maxSelection()\"\n [disabled]=\"_disabled()\"\n (dateChange)=\"_handleChange($event)\"\n />\n <ng-content select=\"[hlmDatePickerFooter]\" />\n </hlm-popover-content>\n </hlm-popover>\n ", isInline: true, dependencies: [{ kind: "directive", type: i2.HlmPopover, selector: "[hlmPopover],hlm-popover" }, { kind: "directive", type: i2.HlmPopoverContent, selector: "[hlmPopoverContent],hlm-popover-content" }, { kind: "directive", type: i2.HlmPopoverPortal, selector: "[hlmPopoverPortal]" }, { kind: "component", type: HlmCalendarMulti, selector: "hlm-calendar-multi", inputs: ["captionLayout"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
666
825
|
}
|
|
667
826
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDatePickerMulti, decorators: [{
|
|
668
827
|
type: Component,
|
|
@@ -670,6 +829,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
670
829
|
selector: 'hlm-date-picker-multi',
|
|
671
830
|
imports: [HlmPopoverImports, HlmCalendarMulti],
|
|
672
831
|
providers: [
|
|
832
|
+
HlmDatePickerCommitState,
|
|
673
833
|
HLM_DATE_PICKER_MUTLI_VALUE_ACCESSOR,
|
|
674
834
|
provideBrnDatePicker(HlmDatePickerMulti),
|
|
675
835
|
provideBrnLabelable(HlmDatePickerMulti),
|
|
@@ -679,7 +839,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
679
839
|
host: { class: 'block' },
|
|
680
840
|
template: "\n <hlm-popover sideOffset=\"5\" [state]=\"_popoverState()\" (stateChanged)=\"_onStateChange($event)\">\n <ng-content />\n\n <hlm-popover-content class=\"w-fit p-0\" *hlmPopoverPortal=\"let ctx\">\n <ng-content select=\"[hlmDatePickerHeader]\" />\n <hlm-calendar-multi\n class=\"rounded-none border-0\"\n [date]=\"_mutableDate()\"\n [captionLayout]=\"captionLayout()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [minSelection]=\"minSelection()\"\n [maxSelection]=\"maxSelection()\"\n [disabled]=\"_disabled()\"\n (dateChange)=\"_handleChange($event)\"\n />\n <ng-content select=\"[hlmDatePickerFooter]\" />\n </hlm-popover-content>\n </hlm-popover>\n ",
|
|
681
841
|
}]
|
|
682
|
-
}], propDecorators: { popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnPopover), { isSignal: true }] }], _trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BrnDatePickerTriggerToken), { isSignal: true }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], minSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSelection", required: false }] }], maxSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelection", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }], autoCloseOnMaxSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCloseOnMaxSelection", required: false }] }], formatDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatDates", required: false }] }], transformDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformDates", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
|
|
842
|
+
}], propDecorators: { _calendar: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnCalendarMulti), { isSignal: true }] }], popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnPopover), { isSignal: true }] }], _trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BrnDatePickerTriggerToken), { isSignal: true }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], minSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSelection", required: false }] }], maxSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelection", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }], autoCloseOnMaxSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCloseOnMaxSelection", required: false }] }], formatDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatDates", required: false }] }], transformDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformDates", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
|
|
683
843
|
|
|
684
844
|
class HlmDatePickerTrigger {
|
|
685
845
|
static _nextId = 0;
|
|
@@ -747,7 +907,7 @@ function getDefaultConfig$1() {
|
|
|
747
907
|
if (isNaN(start.getTime()))
|
|
748
908
|
return null;
|
|
749
909
|
const end = parts.length === 2 ? new Date(parts[1]) : start;
|
|
750
|
-
return
|
|
910
|
+
return isNaN(end.getTime()) ? null : [start, end];
|
|
751
911
|
},
|
|
752
912
|
};
|
|
753
913
|
}
|
|
@@ -760,7 +920,7 @@ function injectHlmDateRangePickerConfig() {
|
|
|
760
920
|
return injectedConfig ? injectedConfig : getDefaultConfig$1();
|
|
761
921
|
}
|
|
762
922
|
|
|
763
|
-
class HlmDateRangeInput extends
|
|
923
|
+
class HlmDateRangeInput extends HlmConstrainedDateInput {
|
|
764
924
|
_config = injectHlmDateRangePickerConfig();
|
|
765
925
|
/** Native `name` attribute forwarded to the inner `<input>`. */
|
|
766
926
|
name = input(undefined, /* @ts-ignore */
|
|
@@ -784,8 +944,8 @@ class HlmDateRangeInput extends BrnDateInput {
|
|
|
784
944
|
}
|
|
785
945
|
/**
|
|
786
946
|
* Parses input text into a date range. Return `null` for invalid
|
|
787
|
-
* input
|
|
788
|
-
*
|
|
947
|
+
* input. Rejected text stays editable and aria-invalid; the committed value
|
|
948
|
+
* is preserved. Empty text explicitly clears on blur/Enter.
|
|
789
949
|
*
|
|
790
950
|
* Defaults to `parseDate` from `HlmDateRangePickerConfig`.
|
|
791
951
|
*/
|
|
@@ -818,7 +978,8 @@ class HlmDateRangeInput extends BrnDateInput {
|
|
|
818
978
|
[placeholder]="placeholder()"
|
|
819
979
|
[readonly]="readonly()"
|
|
820
980
|
[disabled]="_disabled()"
|
|
821
|
-
[
|
|
981
|
+
[attr.aria-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
|
|
982
|
+
[attr.data-matches-spartan-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
|
|
822
983
|
[class]="$inputClass()"
|
|
823
984
|
(click)="_handleClick()"
|
|
824
985
|
(keydown.arrowDown)="_open()"
|
|
@@ -872,7 +1033,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
872
1033
|
[placeholder]="placeholder()"
|
|
873
1034
|
[readonly]="readonly()"
|
|
874
1035
|
[disabled]="_disabled()"
|
|
875
|
-
[
|
|
1036
|
+
[attr.aria-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
|
|
1037
|
+
[attr.data-matches-spartan-invalid]="forceInvalid() || inputInvalid() ? 'true' : null"
|
|
876
1038
|
[class]="$inputClass()"
|
|
877
1039
|
(click)="_handleClick()"
|
|
878
1040
|
(keydown.arrowDown)="_open()"
|
|
@@ -915,6 +1077,11 @@ const HLM_DATE_RANGE_PICKER_VALUE_ACCESSOR = {
|
|
|
915
1077
|
};
|
|
916
1078
|
class HlmDateRangePicker {
|
|
917
1079
|
_config = injectHlmDateRangePickerConfig();
|
|
1080
|
+
_dateAdapter = injectDateAdapter();
|
|
1081
|
+
_commitState = inject(HlmDatePickerCommitState);
|
|
1082
|
+
_calendar = viewChild((BrnCalendarRange), /* @ts-ignore */
|
|
1083
|
+
...(ngDevMode ? [{ debugName: "_calendar" }] : /* istanbul ignore next */ []));
|
|
1084
|
+
_restoringCalendar = false;
|
|
918
1085
|
popover = viewChild.required(BrnPopover, /* @ts-ignore */
|
|
919
1086
|
...(ngDevMode ? [{ debugName: "popover" }] : /* istanbul ignore next */ []));
|
|
920
1087
|
_trigger = contentChild(BrnDatePickerTriggerToken, /* @ts-ignore */
|
|
@@ -979,50 +1146,85 @@ class HlmDateRangePicker {
|
|
|
979
1146
|
}
|
|
980
1147
|
}
|
|
981
1148
|
_handleStartDayChange(value) {
|
|
1149
|
+
if (this._restoringCalendar)
|
|
1150
|
+
return;
|
|
1151
|
+
if (this._disabled() || (value != null && !isSelectableDate(this._dateAdapter, value, this.min(), this.max()))) {
|
|
1152
|
+
this._restoreCalendar();
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
982
1155
|
this._start.set(value);
|
|
983
1156
|
}
|
|
984
1157
|
_handleEndDateChange(value) {
|
|
985
|
-
this.
|
|
986
|
-
|
|
1158
|
+
if (this._restoringCalendar)
|
|
1159
|
+
return;
|
|
1160
|
+
if (this._disabled()) {
|
|
1161
|
+
this._restoreCalendar();
|
|
987
1162
|
return;
|
|
1163
|
+
}
|
|
1164
|
+
if (value == null) {
|
|
1165
|
+
this._end.set(undefined);
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
988
1168
|
const start = this._start();
|
|
989
|
-
if (start
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
1169
|
+
if (start != null) {
|
|
1170
|
+
if (!this.updateDate([start, value])) {
|
|
1171
|
+
this._restoreCalendar();
|
|
1172
|
+
return;
|
|
1173
|
+
}
|
|
994
1174
|
if (this.autoCloseOnEndSelection()) {
|
|
995
1175
|
this._popoverState.set('closed');
|
|
996
1176
|
}
|
|
997
1177
|
}
|
|
998
1178
|
}
|
|
1179
|
+
_restoreCalendar() {
|
|
1180
|
+
this._start.set(this._mutableDate()?.[0]);
|
|
1181
|
+
this._end.set(this._mutableDate()?.[1]);
|
|
1182
|
+
this._restoringCalendar = true;
|
|
1183
|
+
try {
|
|
1184
|
+
this._calendar()?.startDate.set(this._start());
|
|
1185
|
+
this._calendar()?.endDate.set(this._end());
|
|
1186
|
+
}
|
|
1187
|
+
finally {
|
|
1188
|
+
this._restoringCalendar = false;
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
999
1191
|
/**
|
|
1000
|
-
* Commit a range
|
|
1001
|
-
*
|
|
1002
|
-
*
|
|
1192
|
+
* Commit a user range (null clears). Both raw/transformed endpoints must
|
|
1193
|
+
* satisfy adapter whole-day bounds; the transformed range must be ordered.
|
|
1194
|
+
* Returns false without changing/emitting the model on rejection or disabled.
|
|
1003
1195
|
*/
|
|
1004
1196
|
updateDate(value) {
|
|
1005
1197
|
if (this._disabled())
|
|
1006
|
-
return;
|
|
1198
|
+
return false;
|
|
1007
1199
|
if (!value) {
|
|
1008
1200
|
this._mutableDate.set(undefined);
|
|
1009
1201
|
this._start.set(undefined);
|
|
1010
1202
|
this._end.set(undefined);
|
|
1203
|
+
this._commitState.changed();
|
|
1011
1204
|
this._onChange?.(null);
|
|
1012
1205
|
this.dateChange.emit(null);
|
|
1013
|
-
return;
|
|
1206
|
+
return true;
|
|
1014
1207
|
}
|
|
1208
|
+
if (!this._isRangeAllowed(value))
|
|
1209
|
+
return false;
|
|
1015
1210
|
const transformedDates = this.transformDates()(value);
|
|
1211
|
+
if (!this._isRangeAllowed(transformedDates) || this._dateAdapter.isAfter(transformedDates[0], transformedDates[1]))
|
|
1212
|
+
return false;
|
|
1016
1213
|
this._mutableDate.set(transformedDates);
|
|
1017
1214
|
this._start.set(transformedDates[0]);
|
|
1018
1215
|
this._end.set(transformedDates[1]);
|
|
1216
|
+
this._commitState.changed();
|
|
1019
1217
|
this._onChange?.(transformedDates);
|
|
1020
1218
|
this.dateChange.emit(transformedDates);
|
|
1219
|
+
return true;
|
|
1220
|
+
}
|
|
1221
|
+
_isRangeAllowed(dates) {
|
|
1222
|
+
return (dates?.length === 2 && dates.every((date) => isSelectableDate(this._dateAdapter, date, this.min(), this.max())));
|
|
1021
1223
|
}
|
|
1022
1224
|
touched() {
|
|
1023
1225
|
this._onTouched?.();
|
|
1024
1226
|
}
|
|
1025
|
-
/**
|
|
1227
|
+
/** Programmatic CVA write: transforms without enforcing user constraints or emitting. Clears rejected text. */
|
|
1026
1228
|
writeValue(value) {
|
|
1027
1229
|
untracked(() => {
|
|
1028
1230
|
if (!value) {
|
|
@@ -1031,6 +1233,7 @@ class HlmDateRangePicker {
|
|
|
1031
1233
|
else {
|
|
1032
1234
|
this._mutableDate.set(this.transformDates()(value));
|
|
1033
1235
|
}
|
|
1236
|
+
this._commitState.changed();
|
|
1034
1237
|
});
|
|
1035
1238
|
}
|
|
1036
1239
|
registerOnChange(fn) {
|
|
@@ -1052,6 +1255,7 @@ class HlmDateRangePicker {
|
|
|
1052
1255
|
this._mutableDate.set(undefined);
|
|
1053
1256
|
this._start.set(undefined);
|
|
1054
1257
|
this._end.set(undefined);
|
|
1258
|
+
this._commitState.changed();
|
|
1055
1259
|
this._onChange?.(null);
|
|
1056
1260
|
this.dateChange.emit(null);
|
|
1057
1261
|
}
|
|
@@ -1064,10 +1268,11 @@ class HlmDateRangePicker {
|
|
|
1064
1268
|
}
|
|
1065
1269
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDateRangePicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1066
1270
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.3", type: HlmDateRangePicker, isStandalone: true, selector: "hlm-date-range-picker", inputs: { captionLayout: { classPropertyName: "captionLayout", publicName: "captionLayout", 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 }, date: { classPropertyName: "date", publicName: "date", isSignal: true, isRequired: false, transformFunction: null }, autoCloseOnEndSelection: { classPropertyName: "autoCloseOnEndSelection", publicName: "autoCloseOnEndSelection", isSignal: true, isRequired: false, transformFunction: null }, formatDates: { classPropertyName: "formatDates", publicName: "formatDates", isSignal: true, isRequired: false, transformFunction: null }, transformDates: { classPropertyName: "transformDates", publicName: "transformDates", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { dateChange: "dateChange" }, host: { classAttribute: "block" }, providers: [
|
|
1271
|
+
HlmDatePickerCommitState,
|
|
1067
1272
|
HLM_DATE_RANGE_PICKER_VALUE_ACCESSOR,
|
|
1068
1273
|
provideBrnDatePicker(HlmDateRangePicker),
|
|
1069
1274
|
provideBrnLabelable(HlmDateRangePicker),
|
|
1070
|
-
], queries: [{ propertyName: "_trigger", first: true, predicate: BrnDatePickerTriggerToken, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "popover", first: true, predicate: BrnPopover, descendants: true, isSignal: true }], hostDirectives: [{ directive: i1$1.BrnFieldControl }], ngImport: i0, template: "\n <hlm-popover sideOffset=\"5\" [state]=\"_popoverState()\" (stateChanged)=\"_onStateChange($event)\">\n <ng-content />\n\n <hlm-popover-content class=\"w-fit p-0\" *hlmPopoverPortal=\"let ctx\">\n <ng-content select=\"[hlmDatePickerHeader]\" />\n <hlm-calendar-range\n class=\"rounded-none border-0\"\n [startDate]=\"_start()\"\n [captionLayout]=\"captionLayout()\"\n [endDate]=\"_end()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [disabled]=\"_disabled()\"\n (startDateChange)=\"_handleStartDayChange($event)\"\n (endDateChange)=\"_handleEndDateChange($event)\"\n />\n <ng-content select=\"[hlmDatePickerFooter]\" />\n </hlm-popover-content>\n </hlm-popover>\n ", isInline: true, dependencies: [{ kind: "directive", type: i2.HlmPopover, selector: "[hlmPopover],hlm-popover" }, { kind: "directive", type: i2.HlmPopoverContent, selector: "[hlmPopoverContent],hlm-popover-content" }, { kind: "directive", type: i2.HlmPopoverPortal, selector: "[hlmPopoverPortal]" }, { kind: "component", type: HlmCalendarRange, selector: "hlm-calendar-range", inputs: ["captionLayout"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1275
|
+
], queries: [{ propertyName: "_trigger", first: true, predicate: BrnDatePickerTriggerToken, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_calendar", first: true, predicate: (BrnCalendarRange), descendants: true, isSignal: true }, { propertyName: "popover", first: true, predicate: BrnPopover, descendants: true, isSignal: true }], hostDirectives: [{ directive: i1$1.BrnFieldControl }], ngImport: i0, template: "\n <hlm-popover sideOffset=\"5\" [state]=\"_popoverState()\" (stateChanged)=\"_onStateChange($event)\">\n <ng-content />\n\n <hlm-popover-content class=\"w-fit p-0\" *hlmPopoverPortal=\"let ctx\">\n <ng-content select=\"[hlmDatePickerHeader]\" />\n <hlm-calendar-range\n class=\"rounded-none border-0\"\n [startDate]=\"_start()\"\n [captionLayout]=\"captionLayout()\"\n [endDate]=\"_end()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [disabled]=\"_disabled()\"\n (startDateChange)=\"_handleStartDayChange($event)\"\n (endDateChange)=\"_handleEndDateChange($event)\"\n />\n <ng-content select=\"[hlmDatePickerFooter]\" />\n </hlm-popover-content>\n </hlm-popover>\n ", isInline: true, dependencies: [{ kind: "directive", type: i2.HlmPopover, selector: "[hlmPopover],hlm-popover" }, { kind: "directive", type: i2.HlmPopoverContent, selector: "[hlmPopoverContent],hlm-popover-content" }, { kind: "directive", type: i2.HlmPopoverPortal, selector: "[hlmPopoverPortal]" }, { kind: "component", type: HlmCalendarRange, selector: "hlm-calendar-range", inputs: ["captionLayout"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1071
1276
|
}
|
|
1072
1277
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmDateRangePicker, decorators: [{
|
|
1073
1278
|
type: Component,
|
|
@@ -1075,6 +1280,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
1075
1280
|
selector: 'hlm-date-range-picker',
|
|
1076
1281
|
imports: [HlmPopoverImports, HlmCalendarRange],
|
|
1077
1282
|
providers: [
|
|
1283
|
+
HlmDatePickerCommitState,
|
|
1078
1284
|
HLM_DATE_RANGE_PICKER_VALUE_ACCESSOR,
|
|
1079
1285
|
provideBrnDatePicker(HlmDateRangePicker),
|
|
1080
1286
|
provideBrnLabelable(HlmDateRangePicker),
|
|
@@ -1084,7 +1290,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
1084
1290
|
host: { class: 'block' },
|
|
1085
1291
|
template: "\n <hlm-popover sideOffset=\"5\" [state]=\"_popoverState()\" (stateChanged)=\"_onStateChange($event)\">\n <ng-content />\n\n <hlm-popover-content class=\"w-fit p-0\" *hlmPopoverPortal=\"let ctx\">\n <ng-content select=\"[hlmDatePickerHeader]\" />\n <hlm-calendar-range\n class=\"rounded-none border-0\"\n [startDate]=\"_start()\"\n [captionLayout]=\"captionLayout()\"\n [endDate]=\"_end()\"\n [min]=\"min()\"\n [max]=\"max()\"\n [disabled]=\"_disabled()\"\n (startDateChange)=\"_handleStartDayChange($event)\"\n (endDateChange)=\"_handleEndDateChange($event)\"\n />\n <ng-content select=\"[hlmDatePickerFooter]\" />\n </hlm-popover-content>\n </hlm-popover>\n ",
|
|
1086
1292
|
}]
|
|
1087
|
-
}], propDecorators: { popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnPopover), { isSignal: true }] }], _trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BrnDatePickerTriggerToken), { isSignal: true }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", 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 }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }], autoCloseOnEndSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCloseOnEndSelection", required: false }] }], formatDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatDates", required: false }] }], transformDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformDates", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
|
|
1293
|
+
}], propDecorators: { _calendar: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnCalendarRange), { isSignal: true }] }], popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => BrnPopover), { isSignal: true }] }], _trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => BrnDatePickerTriggerToken), { isSignal: true }] }], captionLayout: [{ type: i0.Input, args: [{ isSignal: true, alias: "captionLayout", 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 }] }], date: [{ type: i0.Input, args: [{ isSignal: true, alias: "date", required: false }] }], autoCloseOnEndSelection: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCloseOnEndSelection", required: false }] }], formatDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatDates", required: false }] }], transformDates: [{ type: i0.Input, args: [{ isSignal: true, alias: "transformDates", required: false }] }], dateChange: [{ type: i0.Output, args: ["dateChange"] }] } });
|
|
1088
1294
|
|
|
1089
1295
|
const mmYYYY = (date) => {
|
|
1090
1296
|
if (!(date instanceof Date))
|