@spartan-ng/cli 1.0.4 → 1.1.0-alpha.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.
Files changed (42) hide show
  1. package/package.json +1 -1
  2. package/src/generators/base/generator.js +9 -3
  3. package/src/generators/base/generator.js.map +1 -1
  4. package/src/generators/base/lib/build-dependency-array.js +1 -1
  5. package/src/generators/base/lib/build-dependency-array.js.map +1 -1
  6. package/src/generators/base/lib/package-json-dependencies.d.ts +7 -0
  7. package/src/generators/base/lib/package-json-dependencies.js +17 -0
  8. package/src/generators/base/lib/package-json-dependencies.js.map +1 -0
  9. package/src/generators/base/lib/styles/transform-style-map.js +15 -5
  10. package/src/generators/base/lib/styles/transform-style-map.js.map +1 -1
  11. package/src/generators/healthcheck/generator.js +2 -0
  12. package/src/generators/healthcheck/generator.js.map +1 -1
  13. package/src/generators/healthcheck/healthchecks/scaffold-integrity.d.ts +2 -0
  14. package/src/generators/healthcheck/healthchecks/scaffold-integrity.js +40 -0
  15. package/src/generators/healthcheck/healthchecks/scaffold-integrity.js.map +1 -0
  16. package/src/generators/init/generator.js +3 -3
  17. package/src/generators/init/generator.js.map +1 -1
  18. package/src/generators/ui/libs/calendar/files/index.ts.template +3 -1
  19. package/src/generators/ui/libs/calendar/files/lib/hlm-month-year-calendar.ts.template +115 -0
  20. package/src/generators/ui/libs/date-picker/files/index.ts.template +13 -1
  21. package/src/generators/ui/libs/date-picker/files/lib/hlm-date-multi-input.ts.template +85 -0
  22. package/src/generators/ui/libs/date-picker/files/lib/hlm-date-picker-input.ts.template +23 -124
  23. package/src/generators/ui/libs/date-picker/files/lib/hlm-date-picker-multi.token.ts.template +57 -0
  24. package/src/generators/ui/libs/date-picker/files/lib/hlm-date-picker-multi.ts.template +25 -5
  25. package/src/generators/ui/libs/date-picker/files/lib/hlm-date-picker-trigger.ts.template +8 -5
  26. package/src/generators/ui/libs/date-picker/files/lib/hlm-date-picker.token.ts.template +14 -36
  27. package/src/generators/ui/libs/date-picker/files/lib/hlm-date-picker.ts.template +18 -15
  28. package/src/generators/ui/libs/date-picker/files/lib/hlm-date-range-input.ts.template +86 -0
  29. package/src/generators/ui/libs/date-picker/files/lib/hlm-date-range-picker.token.ts.template +36 -1
  30. package/src/generators/ui/libs/date-picker/files/lib/hlm-date-range-picker.ts.template +38 -7
  31. package/src/generators/ui/libs/date-picker/files/lib/hlm-month-year-input.ts.template +86 -0
  32. package/src/generators/ui/libs/date-picker/files/lib/hlm-month-year-picker.token.ts.template +85 -0
  33. package/src/generators/ui/libs/date-picker/files/lib/hlm-month-year-picker.ts.template +185 -0
  34. package/src/generators/ui/libs/dialog/files/lib/hlm-dialog.service.ts.template +16 -3
  35. package/src/generators/ui/libs/sidebar/files/lib/hlm-sidebar-trigger.ts.template +1 -1
  36. package/src/generators/ui/primitive-deps.js +5 -5
  37. package/src/generators/ui/primitive-deps.js.map +1 -1
  38. package/src/generators/ui/supported-ui-libraries.json +44 -43
  39. package/src/utils/version-utils.d.ts +1 -0
  40. package/src/utils/version-utils.js +13 -0
  41. package/src/utils/version-utils.js.map +1 -1
  42. package/src/generators/ui/libs/date-picker/files/lib/hlm-date-picker-trigger.token.ts.template +0 -11
@@ -12,7 +12,16 @@ export interface HlmDateRangePickerConfig<T> {
12
12
  * @param dates
13
13
  * @returns formatted date
14
14
  */
15
- formatDates: (dates: [T | undefined, T | undefined]) => string;
15
+ formatDates: (dates: [T | null, T | null]) => string;
16
+
17
+ /**
18
+ * Defines how the range should be displayed while the input is focused,
19
+ * i.e. the format the user is expected to type in.
20
+ *
21
+ * @param dates
22
+ * @returns formatted range in the input/edit format
23
+ */
24
+ formatInputDates: (dates: [T | null, T | null]) => string;
16
25
 
17
26
  /**
18
27
  * Defines how the date should be transformed before saving to model/form.
@@ -21,6 +30,14 @@ export interface HlmDateRangePickerConfig<T> {
21
30
  * @returns transformed date
22
31
  */
23
32
  transformDates: (dates: [T, T]) => [T, T];
33
+
34
+ /**
35
+ * Parse a user-entered string into a date range.
36
+ *
37
+ * @param value the raw string from the input
38
+ * @returns the parsed range, or `null` when the value can't be parsed
39
+ */
40
+ parseDate: (value: string) => [T, T] | null;
24
41
  }
25
42
 
26
43
  function getDefaultConfig<T>(): HlmDateRangePickerConfig<T> {
@@ -30,8 +47,26 @@ function getDefaultConfig<T>(): HlmDateRangePickerConfig<T> {
30
47
  .filter(Boolean)
31
48
  .map((date) => (date instanceof Date ? date.toDateString() : `${date}`))
32
49
  .join(' - '),
50
+ formatInputDates: (dates) =>
51
+ dates
52
+ .filter(Boolean)
53
+ .map((date) => (date instanceof Date ? date.toDateString() : `${date}`))
54
+ .join(' - '),
33
55
  transformDates: (dates) => dates,
34
56
  autoCloseOnEndSelection: false,
57
+ parseDate: (value) => {
58
+ if (typeof value !== 'string') return null;
59
+
60
+ const parts = value.split(' - ').map((part) => part.trim());
61
+ if (parts.length === 0 || parts.length > 2) return null;
62
+
63
+ const start = new Date(parts[0]);
64
+ if (isNaN(start.getTime())) return null;
65
+
66
+ const end = parts.length === 2 ? new Date(parts[1]) : start;
67
+
68
+ return [start, isNaN(end.getTime()) ? start : end] as [T, T];
69
+ },
35
70
  };
36
71
  }
37
72
 
@@ -14,14 +14,13 @@ import {
14
14
  viewChild,
15
15
  } from '@angular/core';
16
16
  import { type ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
17
+ import { type BrnDatePickerBase, BrnDatePickerTriggerToken, provideBrnDatePicker } from '@spartan-ng/brain/date-picker';
17
18
  import { BrnFieldControl, provideBrnLabelable } from '@spartan-ng/brain/field';
18
19
  import type { ChangeFn, TouchFn } from '@spartan-ng/brain/forms';
19
20
  import type { BrnOverlayState } from '@spartan-ng/brain/overlay';
20
21
  import { BrnPopover } from '@spartan-ng/brain/popover';
21
22
  import { HlmCalendarRange } from '<%- importAlias %>/calendar';
22
23
  import { HlmPopoverImports } from '<%- importAlias %>/popover';
23
- import { HlmDatePickerTriggerToken } from './hlm-date-picker-trigger.token';
24
- import { HlmDatePickerBase, provideHlmDatePicker } from './hlm-date-picker.token';
25
24
  import { injectHlmDateRangePickerConfig } from './hlm-date-range-picker.token';
26
25
 
27
26
  export const HLM_DATE_RANGE_PICKER_VALUE_ACCESSOR = {
@@ -35,7 +34,7 @@ export const HLM_DATE_RANGE_PICKER_VALUE_ACCESSOR = {
35
34
  imports: [HlmPopoverImports, HlmCalendarRange],
36
35
  providers: [
37
36
  HLM_DATE_RANGE_PICKER_VALUE_ACCESSOR,
38
- provideHlmDatePicker(HlmDateRangePicker),
37
+ provideBrnDatePicker(HlmDateRangePicker),
39
38
  provideBrnLabelable(HlmDateRangePicker),
40
39
  ],
41
40
  changeDetection: ChangeDetectionStrategy.OnPush,
@@ -63,12 +62,12 @@ export const HLM_DATE_RANGE_PICKER_VALUE_ACCESSOR = {
63
62
  </hlm-popover>
64
63
  `,
65
64
  })
66
- export class HlmDateRangePicker<T> implements HlmDatePickerBase<T>, ControlValueAccessor {
65
+ export class HlmDateRangePicker<T> implements BrnDatePickerBase<[T, T]>, ControlValueAccessor {
67
66
  private readonly _config = injectHlmDateRangePickerConfig<T>();
68
67
 
69
68
  public readonly popover = viewChild.required(BrnPopover);
70
69
 
71
- private readonly _trigger = contentChild(HlmDatePickerTriggerToken);
70
+ private readonly _trigger = contentChild(BrnDatePickerTriggerToken);
72
71
 
73
72
  /** Show dropdowns to navigate between months or years. */
74
73
  public readonly captionLayout = input<'dropdown' | 'label' | 'dropdown-months' | 'dropdown-years'>('label');
@@ -98,7 +97,7 @@ export class HlmDateRangePicker<T> implements HlmDatePickerBase<T>, ControlValue
98
97
  });
99
98
 
100
99
  /** Defines how the date should be displayed in the UI. */
101
- public readonly formatDates = input<(dates: [T | undefined, T | undefined]) => string>(this._config.formatDates);
100
+ public readonly formatDates = input<(dates: [T | null, T | null]) => string>(this._config.formatDates);
102
101
 
103
102
  /** Defines how the date should be transformed before saving to model/form. */
104
103
  public readonly transformDates = input<(date: [T, T]) => [T, T]>(this._config.transformDates);
@@ -113,7 +112,7 @@ export class HlmDateRangePicker<T> implements HlmDatePickerBase<T>, ControlValue
113
112
  public readonly formattedDate = computed(() => {
114
113
  const start = this._start();
115
114
  const end = this._end();
116
- return start || end ? this.formatDates()([start, end]) : undefined;
115
+ return start || end ? this.formatDates()([start ?? null, end ?? null]) : undefined;
117
116
  });
118
117
 
119
118
  public readonly dateChange = output<[T, T] | null>();
@@ -122,6 +121,9 @@ export class HlmDateRangePicker<T> implements HlmDatePickerBase<T>, ControlValue
122
121
 
123
122
  public readonly hasDate = computed(() => !!this._start() || !!this._end());
124
123
 
124
+ /** @internal The current raw value, used by inputs to reformat on focus. */
125
+ public readonly value = computed(() => this._mutableDate() ?? null);
126
+
125
127
  protected _onChange?: ChangeFn<[T, T] | null>;
126
128
  protected _onTouched?: TouchFn;
127
129
 
@@ -154,6 +156,35 @@ export class HlmDateRangePicker<T> implements HlmDatePickerBase<T>, ControlValue
154
156
  }
155
157
  }
156
158
 
159
+ /**
160
+ * Commit a range to the picker. Updates the internal model, notifies form
161
+ * controls, and emits `dateChange`. Intended to be called from a text input
162
+ * that parses user-entered values. Pass `null` to clear the range.
163
+ */
164
+ public updateDate(value: [T, T] | null) {
165
+ if (this._disabled()) return;
166
+
167
+ if (!value) {
168
+ this._mutableDate.set(undefined);
169
+ this._start.set(undefined);
170
+ this._end.set(undefined);
171
+ this._onChange?.(null);
172
+ this.dateChange.emit(null);
173
+ return;
174
+ }
175
+
176
+ const transformedDates = this.transformDates()(value);
177
+ this._mutableDate.set(transformedDates);
178
+ this._start.set(transformedDates[0]);
179
+ this._end.set(transformedDates[1]);
180
+ this._onChange?.(transformedDates);
181
+ this.dateChange.emit(transformedDates);
182
+ }
183
+
184
+ public touched(): void {
185
+ this._onTouched?.();
186
+ }
187
+
157
188
  /** CONTROL VALUE ACCESSOR */
158
189
  public writeValue(value: [T, T] | null): void {
159
190
  untracked(() => {
@@ -0,0 +1,86 @@
1
+ import { ChangeDetectionStrategy, Component, input } from '@angular/core';
2
+ import { NgIcon, provideIcons } from '@ng-icons/core';
3
+ import { lucideCalendar, lucideX } from '@ng-icons/lucide';
4
+ import {
5
+ BrnDateInput,
6
+ type BrnDatePickerTriggerBase,
7
+ provideBrnDatePickerTrigger,
8
+ } from '@spartan-ng/brain/date-picker';
9
+ import { HlmInputGroup, HlmInputGroupImports } from '<%- importAlias %>/input-group';
10
+ import { injectHlmMonthYearPickerConfig } from './hlm-month-year-picker.token';
11
+
12
+ @Component({
13
+ selector: 'hlm-month-year-input',
14
+ imports: [HlmInputGroupImports, NgIcon],
15
+ providers: [provideIcons({ lucideCalendar, lucideX }), provideBrnDatePickerTrigger(HlmMonthYearInput)],
16
+ changeDetection: ChangeDetectionStrategy.OnPush,
17
+ hostDirectives: [HlmInputGroup],
18
+ template: `
19
+ <input
20
+ #input
21
+ hlmInputGroupInput
22
+ [value]="_inputValue()"
23
+ [id]="inputId()"
24
+ [placeholder]="placeholder()"
25
+ [disabled]="_disabled()"
26
+ [forceInvalid]="forceInvalid()"
27
+ (click)="_handleClick()"
28
+ (keydown.arrowDown)="_open()"
29
+ (keydown.enter)="_handleEnter($event)"
30
+ (input)="_handleInputChange($event)"
31
+ (focus)="_handleFocus()"
32
+ (blur)="_handleBlur()"
33
+ />
34
+ <hlm-input-group-addon align="inline-end">
35
+ @if (_showClearButton()) {
36
+ <button
37
+ hlmInputGroupButton
38
+ size="icon-xs"
39
+ variant="ghost"
40
+ [attr.aria-label]="clearAriaLabel()"
41
+ (click)="_clear()"
42
+ [disabled]="_disabled()"
43
+ >
44
+ <ng-icon name="lucideX" />
45
+ </button>
46
+ }
47
+ <button
48
+ hlmInputGroupButton
49
+ size="icon-xs"
50
+ [attr.aria-label]="calendarAriaLabel()"
51
+ (click)="_popover().open()"
52
+ [disabled]="_disabled()"
53
+ >
54
+ <ng-icon name="lucideCalendar" />
55
+ </button>
56
+ </hlm-input-group-addon>
57
+ `,
58
+ })
59
+ export class HlmMonthYearInput<T> extends BrnDateInput<T> implements BrnDatePickerTriggerBase {
60
+ private readonly _config = injectHlmMonthYearPickerConfig<T>();
61
+
62
+ /**
63
+ * Parses input text into a date value. Return `null` for invalid
64
+ * input - the picker's date is cleared while the text is preserved so
65
+ * the user can fix it.
66
+ *
67
+ * Defaults to `parseDate` from `HlmMonthYearPickerConfig`.
68
+ */
69
+ public readonly parseDate = input<(value: string) => T | null>(this._config.parseDate);
70
+
71
+ /**
72
+ * Formats the current date into the input/edit format shown while the
73
+ * input is focused. On blur the picker's display format is restored.
74
+ *
75
+ * Defaults to `formatInputDate` from `HlmMonthYearPickerConfig`.
76
+ */
77
+ public readonly formatInputDate = input<(date: T) => string>(this._config.formatInputDate);
78
+
79
+ protected override parseValue(value: string): T | null {
80
+ return this.parseDate()(value);
81
+ }
82
+
83
+ protected override formatInputValue(value: T): string {
84
+ return this.formatInputDate()(value);
85
+ }
86
+ }
@@ -0,0 +1,85 @@
1
+ import { inject, InjectionToken, type ValueProvider } from '@angular/core';
2
+
3
+ export interface HlmMonthYearPickerConfig<T> {
4
+ /**
5
+ * If true, the date picker will close when a date is selected.
6
+ */
7
+ autoCloseOnSelect: boolean;
8
+
9
+ /**
10
+ * Defines how the date should be displayed in the UI.
11
+ *
12
+ * @param date
13
+ * @returns formatted date
14
+ */
15
+ formatDate: (date: T) => string;
16
+
17
+ /**
18
+ * Defines how the date should be displayed while the input is focused,
19
+ * i.e. the format the user is expected to type in.
20
+ *
21
+ * @param date
22
+ * @returns formatted date in the input/edit format
23
+ */
24
+ formatInputDate: (date: T) => string;
25
+
26
+ /**
27
+ * Defines how the date should be transformed before saving to model/form.
28
+ *
29
+ * @param date
30
+ * @returns transformed date
31
+ */
32
+ transformDate: (date: T) => T;
33
+
34
+ /**
35
+ * Parse a user-entered string into a date.
36
+ *
37
+ * @param value the raw string from the input
38
+ * @returns the parsed date, or `null` when the value can't be parsed
39
+ */
40
+ parseDate: (value: string) => T | null;
41
+ }
42
+
43
+ const mmYYYY = <T>(date: T) => {
44
+ if (!(date instanceof Date)) return `${date}`;
45
+
46
+ const month = String(date.getMonth() + 1).padStart(2, '0');
47
+ const year = date.getFullYear();
48
+
49
+ return `${month}/${year}`;
50
+ };
51
+
52
+ function getDefaultConfig<T>(): HlmMonthYearPickerConfig<T> {
53
+ return {
54
+ formatDate: mmYYYY,
55
+ formatInputDate: mmYYYY,
56
+ transformDate: (date) => date,
57
+ parseDate: (value) => {
58
+ if (typeof value !== 'string') return null;
59
+
60
+ const match = value.match(/^(\d{2})\/(\d{4})$/);
61
+ if (!match) return null;
62
+
63
+ const month = Number(match[1]);
64
+ const year = Number(match[2]);
65
+
66
+ if (month < 1 || month > 12) return null;
67
+
68
+ const date = new Date(year, month - 1, 1);
69
+
70
+ return date as T;
71
+ },
72
+ autoCloseOnSelect: false,
73
+ };
74
+ }
75
+
76
+ const HlmMonthYearPickerConfigToken = new InjectionToken<HlmMonthYearPickerConfig<unknown>>('HlmMonthYearPickerConfig');
77
+
78
+ export function provideHlmMonthYearPickerConfig<T>(config: Partial<HlmMonthYearPickerConfig<T>>): ValueProvider {
79
+ return { provide: HlmMonthYearPickerConfigToken, useValue: { ...getDefaultConfig(), ...config } };
80
+ }
81
+
82
+ export function injectHlmMonthYearPickerConfig<T>(): HlmMonthYearPickerConfig<T> {
83
+ const injectedConfig = inject(HlmMonthYearPickerConfigToken, { optional: true });
84
+ return injectedConfig ? (injectedConfig as HlmMonthYearPickerConfig<T>) : getDefaultConfig();
85
+ }
@@ -0,0 +1,185 @@
1
+ import type { BooleanInput } from '@angular/cdk/coercion';
2
+ import {
3
+ booleanAttribute,
4
+ ChangeDetectionStrategy,
5
+ Component,
6
+ computed,
7
+ contentChild,
8
+ forwardRef,
9
+ input,
10
+ linkedSignal,
11
+ output,
12
+ signal,
13
+ viewChild,
14
+ } from '@angular/core';
15
+ import { type ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
16
+ import { type BrnDatePickerBase, BrnDatePickerTriggerToken, provideBrnDatePicker } from '@spartan-ng/brain/date-picker';
17
+ import { BrnFieldControl, provideBrnLabelable } from '@spartan-ng/brain/field';
18
+ import type { ChangeFn, TouchFn } from '@spartan-ng/brain/forms';
19
+ import type { BrnOverlayState } from '@spartan-ng/brain/overlay';
20
+ import { BrnPopover } from '@spartan-ng/brain/popover';
21
+ import { HlmCalendarImports } from '<%- importAlias %>/calendar';
22
+ import { HlmPopoverImports } from '<%- importAlias %>/popover';
23
+ import { injectHlmMonthYearPickerConfig } from './hlm-month-year-picker.token';
24
+
25
+ export const HLM_MONTH_YEAR_PICKER_VALUE_ACCESSOR = {
26
+ provide: NG_VALUE_ACCESSOR,
27
+ useExisting: forwardRef(() => HlmMonthYearPicker),
28
+ multi: true,
29
+ };
30
+ @Component({
31
+ selector: 'hlm-month-year-picker',
32
+ imports: [HlmPopoverImports, HlmCalendarImports],
33
+ providers: [
34
+ HLM_MONTH_YEAR_PICKER_VALUE_ACCESSOR,
35
+ provideBrnDatePicker(HlmMonthYearPicker),
36
+ provideBrnLabelable(HlmMonthYearPicker),
37
+ ],
38
+ changeDetection: ChangeDetectionStrategy.OnPush,
39
+ hostDirectives: [BrnFieldControl],
40
+ host: { class: 'block' },
41
+ template: `
42
+ <hlm-popover sideOffset="5" [state]="_popoverState()" (stateChanged)="_onStateChange($event)">
43
+ <ng-content />
44
+
45
+ <hlm-popover-content class="w-fit p-0" *hlmPopoverPortal="let ctx">
46
+ <ng-content select="[hlmDatePickerHeader]" />
47
+ <hlm-month-year-calendar
48
+ class="rounded-none border-0"
49
+ [date]="_mutableDate()"
50
+ [defaultFocusedDate]="_mutableDate() ?? defaultFocusedDate()"
51
+ [min]="min()"
52
+ [max]="max()"
53
+ [disabled]="_disabled()"
54
+ (dateChange)="_handleChange($event)"
55
+ />
56
+ <ng-content select="[hlmDatePickerFooter]" />
57
+ </hlm-popover-content>
58
+ </hlm-popover>
59
+ `,
60
+ })
61
+ export class HlmMonthYearPicker<T> implements BrnDatePickerBase<T>, ControlValueAccessor {
62
+ private readonly _config = injectHlmMonthYearPickerConfig<T>();
63
+
64
+ public readonly popover = viewChild.required(BrnPopover);
65
+
66
+ private readonly _trigger = contentChild(BrnDatePickerTriggerToken);
67
+
68
+ /** The minimum date that can be selected.*/
69
+ public readonly min = input<T>();
70
+
71
+ /** The maximum date that can be selected. */
72
+ public readonly max = input<T>();
73
+
74
+ /** Determine if the date picker is disabled. */
75
+ public readonly disabled = input<boolean, BooleanInput>(false, {
76
+ transform: booleanAttribute,
77
+ });
78
+
79
+ /** The selected value. */
80
+ public readonly date = input<T>();
81
+
82
+ /** The date the calendar focuses on first open when no date is selected. */
83
+ public readonly defaultFocusedDate = input<T>();
84
+
85
+ protected readonly _mutableDate = linkedSignal(this.date);
86
+
87
+ /** If true, the date picker will close when a date is selected. */
88
+ public readonly autoCloseOnSelect = input<boolean, BooleanInput>(this._config.autoCloseOnSelect, {
89
+ transform: booleanAttribute,
90
+ });
91
+
92
+ /** Defines how the date should be displayed in the UI. */
93
+ public readonly formatDate = input<(date: T) => string>(this._config.formatDate);
94
+
95
+ /** Defines how the date should be transformed before saving to model/form. */
96
+ public readonly transformDate = input<(date: T) => T>(this._config.transformDate);
97
+
98
+ protected readonly _popoverState = signal<BrnOverlayState | null>(null);
99
+
100
+ protected readonly _disabled = linkedSignal(this.disabled);
101
+
102
+ /** @internal The disabled state as a readonly signal */
103
+ public readonly disabledState = this._disabled.asReadonly();
104
+
105
+ public readonly formattedDate = computed(() => {
106
+ const date = this._mutableDate();
107
+ return date ? this.formatDate()(date) : undefined;
108
+ });
109
+
110
+ public readonly dateChange = output<T | null>();
111
+
112
+ public readonly labelableId = computed(() => this._trigger()?.triggerId());
113
+
114
+ public readonly hasDate = computed(() => !!this._mutableDate());
115
+
116
+ /** @internal The current raw value, used by inputs to reformat on focus. */
117
+ public readonly value = computed(() => this._mutableDate() ?? null);
118
+
119
+ protected _onChange?: ChangeFn<T | null>;
120
+ protected _onTouched?: TouchFn;
121
+
122
+ protected _onStateChange(state: BrnOverlayState) {
123
+ this._popoverState.set(state);
124
+ if (state === 'closed') this._onTouched?.();
125
+ }
126
+
127
+ protected _handleChange(value: T | undefined) {
128
+ if (this._disabled()) return;
129
+ this.updateDate(value ?? null);
130
+
131
+ if (this.autoCloseOnSelect()) {
132
+ this._popoverState.set('closed');
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Commit a date to the picker. Updates the internal model, notifies form
138
+ * controls, and emits `dateChange`. Unlike `_handleChange`, this does not
139
+ * close the popover - it's intended to be called from a text input that
140
+ * is parsing user-entered values while typing.
141
+ */
142
+ public updateDate(value: T | null) {
143
+ if (this._disabled()) return;
144
+ const transformedDate = value != null ? this.transformDate()(value) : undefined;
145
+
146
+ this._mutableDate.set(transformedDate);
147
+ this._onChange?.(transformedDate ?? null);
148
+ this.dateChange.emit(transformedDate ?? null);
149
+ }
150
+
151
+ /** CONTROL VALUE ACCESSOR */
152
+ public writeValue(value: T | null): void {
153
+ this._mutableDate.set(value ? this.transformDate()(value) : undefined);
154
+ }
155
+
156
+ public registerOnChange(fn: ChangeFn<T | null>): void {
157
+ this._onChange = fn;
158
+ }
159
+
160
+ public registerOnTouched(fn: TouchFn): void {
161
+ this._onTouched = fn;
162
+ }
163
+
164
+ public touched(): void {
165
+ this._onTouched?.();
166
+ }
167
+
168
+ public setDisabledState(isDisabled: boolean): void {
169
+ this._disabled.set(isDisabled);
170
+ }
171
+
172
+ public open() {
173
+ this._popoverState.set('open');
174
+ }
175
+
176
+ public close() {
177
+ this._popoverState.set('closed');
178
+ }
179
+
180
+ public reset() {
181
+ this._mutableDate.set(undefined);
182
+ this._onChange?.(null);
183
+ this.dateChange.emit(null);
184
+ }
185
+ }
@@ -1,6 +1,11 @@
1
1
  import type { ComponentType } from '@angular/cdk/portal';
2
2
  import { inject, Injectable, type TemplateRef } from '@angular/core';
3
- import { type BrnDialogOptions, BrnDialogService, cssClassesToArray } from '@spartan-ng/brain/dialog';
3
+ import {
4
+ type BrnDialogOptions,
5
+ type BrnDialogRef,
6
+ BrnDialogService,
7
+ cssClassesToArray,
8
+ } from '@spartan-ng/brain/dialog';
4
9
  import { HlmDialogContent } from './hlm-dialog-content';
5
10
  import { hlmDialogOverlayClass } from './hlm-dialog-overlay';
6
11
 
@@ -16,7 +21,10 @@ export type HlmDialogOptions<DialogContext = unknown> = BrnDialogOptions & {
16
21
  export class HlmDialogService {
17
22
  private readonly _brnDialogService = inject(BrnDialogService);
18
23
 
19
- public open(component: ComponentType<unknown> | TemplateRef<unknown>, options?: Partial<HlmDialogOptions>) {
24
+ public open<TResult = unknown, TContext = unknown>(
25
+ component: ComponentType<unknown> | TemplateRef<unknown>,
26
+ options?: Partial<HlmDialogOptions<TContext>>,
27
+ ): BrnDialogRef<TResult> {
20
28
  const mergedOptions = {
21
29
  ...(options ?? {}),
22
30
  backdropClass: cssClassesToArray(`${hlmDialogOverlayClass} ${options?.backdropClass ?? ''}`),
@@ -28,6 +36,11 @@ export class HlmDialogService {
28
36
  },
29
37
  };
30
38
 
31
- return this._brnDialogService.open(HlmDialogContent, undefined, mergedOptions.context, mergedOptions);
39
+ return this._brnDialogService.open<unknown, TResult>(
40
+ HlmDialogContent,
41
+ undefined,
42
+ mergedOptions.context,
43
+ mergedOptions,
44
+ );
32
45
  }
33
46
  }
@@ -24,7 +24,7 @@ import { HlmSidebarService } from './hlm-sidebar.service';
24
24
  export class HlmSidebarTrigger {
25
25
  private readonly _sidebarService = inject(HlmSidebarService);
26
26
 
27
- public readonly srOnlyText = input('Toggle Sidebar');
27
+ public readonly srOnlyText = input<string>('Toggle Sidebar');
28
28
 
29
29
  protected _onClick(): void {
30
30
  this._sidebarService.toggleSidebar();
@@ -18,10 +18,10 @@ exports.primitiveDependencies = {
18
18
  checkbox: ['utils'],
19
19
  collapsible: ['utils'],
20
20
  combobox: ['utils', 'input-group', 'button'],
21
- command: ['utils', 'button'],
21
+ command: ['utils', 'button', 'input-group', 'dialog'],
22
22
  'context-menu': ['utils', 'dropdown-menu'],
23
- 'date-picker': ['utils', 'calendar', 'popover'],
24
- dialog: ['utils'],
23
+ 'date-picker': ['utils', 'calendar', 'popover', 'input-group'],
24
+ dialog: ['utils', 'button'],
25
25
  drawer: ['utils'],
26
26
  'dropdown-menu': ['utils'],
27
27
  empty: ['utils'],
@@ -52,11 +52,11 @@ exports.primitiveDependencies = {
52
52
  spinner: ['utils'],
53
53
  switch: ['utils'],
54
54
  table: ['utils'],
55
- tabs: ['utils'],
55
+ tabs: ['utils', 'button'],
56
56
  textarea: ['utils'],
57
57
  toggle: ['utils'],
58
58
  'toggle-group': ['utils', 'toggle'],
59
- tooltip: [],
59
+ tooltip: ['utils'],
60
60
  typography: ['utils'],
61
61
  utils: [],
62
62
  };
@@ -1 +1 @@
1
- {"version":3,"file":"primitive-deps.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/generators/ui/primitive-deps.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"primitive-deps.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/generators/ui/primitive-deps.ts"],"names":[],"mappings":"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"}