@spartan-ng/cli 0.0.1-alpha.657 → 0.0.1-alpha.659
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/package.json +1 -1
- package/src/generators/healthcheck/generator.js +2 -0
- package/src/generators/healthcheck/generator.js.map +1 -1
- package/src/generators/healthcheck/healthchecks/hlm-form-field.d.ts +2 -0
- package/src/generators/healthcheck/healthchecks/hlm-form-field.js +35 -0
- package/src/generators/healthcheck/healthchecks/hlm-form-field.js.map +1 -0
- package/src/generators/migrate-form-field/compat.d.ts +2 -0
- package/src/generators/migrate-form-field/compat.js +6 -0
- package/src/generators/migrate-form-field/compat.js.map +1 -0
- package/src/generators/migrate-form-field/generator.d.ts +4 -0
- package/src/generators/migrate-form-field/generator.js +60 -0
- package/src/generators/migrate-form-field/generator.js.map +1 -0
- package/src/generators/migrate-form-field/schema.d.ts +4 -0
- package/src/generators/migrate-form-field/schema.json +19 -0
- package/src/generators/ui/libs/autocomplete/files/lib/hlm-autocomplete-input.ts.template +9 -4
- package/src/generators/ui/libs/badge/files/lib/hlm-badge.ts.template +7 -8
- package/src/generators/ui/libs/card/files/lib/hlm-card-action.ts.template +1 -1
- package/src/generators/ui/libs/card/files/lib/hlm-card-content.ts.template +1 -1
- package/src/generators/ui/libs/card/files/lib/hlm-card-description.ts.template +1 -1
- package/src/generators/ui/libs/card/files/lib/hlm-card-footer.ts.template +1 -4
- package/src/generators/ui/libs/card/files/lib/hlm-card-header.ts.template +1 -1
- package/src/generators/ui/libs/card/files/lib/hlm-card-title.ts.template +1 -1
- package/src/generators/ui/libs/card/files/lib/hlm-card.ts.template +1 -4
- package/src/generators/ui/libs/checkbox/files/lib/hlm-checkbox.ts.template +18 -2
- package/src/generators/ui/libs/combobox/files/lib/hlm-combobox-chip-input.ts.template +1 -1
- package/src/generators/ui/libs/combobox/files/lib/hlm-combobox-chips.ts.template +22 -7
- package/src/generators/ui/libs/combobox/files/lib/hlm-combobox-input.ts.template +8 -4
- package/src/generators/ui/libs/combobox/files/lib/hlm-combobox-trigger.ts.template +10 -1
- package/src/generators/ui/libs/date-picker/files/lib/hlm-date-picker-multi.ts.template +38 -5
- package/src/generators/ui/libs/date-picker/files/lib/hlm-date-picker.ts.template +36 -6
- package/src/generators/ui/libs/date-picker/files/lib/hlm-date-range-picker.ts.template +33 -4
- package/src/generators/ui/libs/field/files/index.ts.template +3 -3
- package/src/generators/ui/libs/field/files/lib/hlm-field-content.ts.template +1 -1
- package/src/generators/ui/libs/field/files/lib/hlm-field-description.ts.template +40 -2
- package/src/generators/ui/libs/field/files/lib/hlm-field-error.ts.template +89 -27
- package/src/generators/ui/libs/field/files/lib/hlm-field-group.ts.template +1 -1
- package/src/generators/ui/libs/field/files/lib/hlm-field-legend.ts.template +2 -2
- package/src/generators/ui/libs/field/files/lib/hlm-field.ts.template +9 -6
- package/src/generators/ui/libs/input/files/lib/hlm-input.ts.template +10 -69
- package/src/generators/ui/libs/input-group/files/lib/hlm-input-group.ts.template +15 -5
- package/src/generators/ui/libs/label/files/lib/hlm-label.ts.template +4 -1
- package/src/generators/ui/libs/native-select/files/lib/hlm-native-select.ts.template +32 -13
- package/src/generators/ui/libs/radio-group/files/lib/hlm-radio-group.ts.template +18 -2
- package/src/generators/ui/libs/radio-group/files/lib/hlm-radio.ts.template +16 -1
- package/src/generators/ui/libs/select/files/lib/hlm-select-trigger.ts.template +5 -2
- package/src/generators/ui/libs/slider/files/lib/hlm-slider.ts.template +3 -4
- package/src/generators/ui/libs/textarea/files/lib/hlm-textarea.ts.template +10 -71
- package/src/generators/ui/primitive-deps.js +0 -1
- package/src/generators/ui/primitive-deps.js.map +1 -1
- package/src/generators/ui/primitives.d.ts +1 -1
- package/src/generators/ui/style-luma.css +1365 -0
- package/src/generators/ui/style-lyra.css +24 -24
- package/src/generators/ui/style-maia.css +24 -24
- package/src/generators/ui/style-mira.css +24 -24
- package/src/generators/ui/style-nova.css +24 -24
- package/src/generators/ui/style-vega.css +24 -24
- package/src/generators/ui/supported-ui-libraries.json +54 -56
- package/src/generators/ui/libs/form-field/files/index.ts.template +0 -9
- package/src/generators/ui/libs/form-field/files/lib/hlm-error.ts.template +0 -12
- package/src/generators/ui/libs/form-field/files/lib/hlm-form-field.ts.template +0 -39
- package/src/generators/ui/libs/form-field/files/lib/hlm-hint.ts.template +0 -12
- package/src/generators/ui/libs/form-field/generator.d.ts +0 -3
- package/src/generators/ui/libs/form-field/generator.js +0 -9
- package/src/generators/ui/libs/form-field/generator.js.map +0 -1
|
@@ -5,19 +5,20 @@ import {
|
|
|
5
5
|
Component,
|
|
6
6
|
computed,
|
|
7
7
|
forwardRef,
|
|
8
|
+
inject,
|
|
8
9
|
input,
|
|
9
10
|
linkedSignal,
|
|
10
11
|
model,
|
|
11
12
|
output,
|
|
12
13
|
} from '@angular/core';
|
|
13
|
-
import { type ControlValueAccessor
|
|
14
|
+
import { NG_VALUE_ACCESSOR, type ControlValueAccessor } from '@angular/forms';
|
|
14
15
|
import { NgIcon, provideIcons } from '@ng-icons/core';
|
|
15
16
|
import { lucideChevronDown } from '@ng-icons/lucide';
|
|
16
|
-
import
|
|
17
|
+
import { BrnFieldControl, provideBrnLabelable } from '@spartan-ng/brain/field';
|
|
18
|
+
import { type ChangeFn, type TouchFn } from '@spartan-ng/brain/forms';
|
|
17
19
|
import { classes, hlm } from '<%- importAlias %>/utils';
|
|
18
20
|
import type { ClassValue } from 'clsx';
|
|
19
21
|
|
|
20
|
-
// TODO support BrnFormFieldControl
|
|
21
22
|
export const HLM_NATIVE_SELECT_VALUE_ACCESSOR = {
|
|
22
23
|
provide: NG_VALUE_ACCESSOR,
|
|
23
24
|
useExisting: forwardRef(() => HlmNativeSelect),
|
|
@@ -27,8 +28,13 @@ export const HLM_NATIVE_SELECT_VALUE_ACCESSOR = {
|
|
|
27
28
|
@Component({
|
|
28
29
|
selector: 'hlm-native-select',
|
|
29
30
|
imports: [NgIcon],
|
|
30
|
-
providers: [
|
|
31
|
+
providers: [
|
|
32
|
+
HLM_NATIVE_SELECT_VALUE_ACCESSOR,
|
|
33
|
+
provideIcons({ lucideChevronDown }),
|
|
34
|
+
provideBrnLabelable(HlmNativeSelect),
|
|
35
|
+
],
|
|
31
36
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
37
|
+
hostDirectives: [BrnFieldControl],
|
|
32
38
|
host: {
|
|
33
39
|
'data-slot': 'native-select-wrapper',
|
|
34
40
|
'[attr.data-size]': 'size()',
|
|
@@ -36,10 +42,14 @@ export const HLM_NATIVE_SELECT_VALUE_ACCESSOR = {
|
|
|
36
42
|
template: `
|
|
37
43
|
<select
|
|
38
44
|
data-slot="native-select"
|
|
39
|
-
[id]="
|
|
45
|
+
[id]="selectId()"
|
|
40
46
|
[class]="_computedSelectClass()"
|
|
41
47
|
[attr.data-size]="size()"
|
|
42
|
-
[attr.aria-invalid]="
|
|
48
|
+
[attr.aria-invalid]="_ariaInvalid() ? 'true' : null"
|
|
49
|
+
[attr.data-invalid]="_ariaInvalid() ? 'true' : null"
|
|
50
|
+
[attr.data-dirty]="_dirty?.() ? 'true' : null"
|
|
51
|
+
[attr.data-touched]="_touched?.() ? 'true' : null"
|
|
52
|
+
[attr.data-matches-spartan-invalid]="_spartanInvalid?.() ? 'true' : null"
|
|
43
53
|
[value]="value()"
|
|
44
54
|
[disabled]="_disabled()"
|
|
45
55
|
(change)="_valueChanged($event)"
|
|
@@ -57,19 +67,18 @@ export const HLM_NATIVE_SELECT_VALUE_ACCESSOR = {
|
|
|
57
67
|
`,
|
|
58
68
|
})
|
|
59
69
|
export class HlmNativeSelect implements ControlValueAccessor {
|
|
60
|
-
private
|
|
70
|
+
private readonly _fieldControl = inject(BrnFieldControl, { optional: true });
|
|
61
71
|
|
|
62
|
-
|
|
72
|
+
private static _id = 0;
|
|
63
73
|
|
|
64
|
-
|
|
74
|
+
public readonly selectId = input<string>(`hlm-native-select-${HlmNativeSelect._id++}`);
|
|
65
75
|
|
|
66
76
|
public readonly selectClass = input<ClassValue>('');
|
|
67
77
|
|
|
68
78
|
protected readonly _computedSelectClass = computed(() =>
|
|
69
79
|
hlm(
|
|
70
80
|
'border-input placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/50 h-9 w-full min-w-0 appearance-none rounded-md border bg-transparent py-1 pr-8 pl-2.5 text-sm shadow-xs transition-[color,box-shadow] outline-none select-none focus-visible:ring-3 disabled:pointer-events-none disabled:cursor-not-allowed data-[size=sm]:h-8',
|
|
71
|
-
|
|
72
|
-
'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 aria-invalid:ring-3',
|
|
81
|
+
'data-[matches-spartan-invalid=true]:ring-destructive/20 dark:data-[matches-spartan-invalid=true]:ring-destructive/40 data-[matches-spartan-invalid=true]:border-destructive dark:data-[matches-spartan-invalid=true]:border-destructive/50 data-[matches-spartan-invalid=true]:ring-3',
|
|
73
82
|
this.selectClass(),
|
|
74
83
|
),
|
|
75
84
|
);
|
|
@@ -89,11 +98,14 @@ export class HlmNativeSelect implements ControlValueAccessor {
|
|
|
89
98
|
|
|
90
99
|
protected readonly _disabled = linkedSignal(this.disabled);
|
|
91
100
|
|
|
92
|
-
|
|
93
|
-
|
|
101
|
+
/** Manual override for aria-invalid. When not set, auto-detects from the parent autocomplete error state. */
|
|
102
|
+
public readonly ariaInvalidOverride = input<boolean | undefined, BooleanInput>(undefined, {
|
|
103
|
+
transform: (v: BooleanInput) => (v === '' || v === undefined ? undefined : booleanAttribute(v)),
|
|
94
104
|
alias: 'aria-invalid',
|
|
95
105
|
});
|
|
96
106
|
|
|
107
|
+
protected readonly _ariaInvalid = computed(() => this.ariaInvalidOverride() ?? this._invalid?.());
|
|
108
|
+
|
|
97
109
|
public readonly value = model<string | null>('');
|
|
98
110
|
|
|
99
111
|
public readonly valueChange = output<string | null>();
|
|
@@ -101,6 +113,13 @@ export class HlmNativeSelect implements ControlValueAccessor {
|
|
|
101
113
|
protected _onChange?: ChangeFn<string | null>;
|
|
102
114
|
protected _onTouched?: TouchFn;
|
|
103
115
|
|
|
116
|
+
public readonly labelableId = this.selectId;
|
|
117
|
+
|
|
118
|
+
protected readonly _invalid = this._fieldControl?.invalid;
|
|
119
|
+
protected readonly _touched = this._fieldControl?.touched;
|
|
120
|
+
protected readonly _dirty = this._fieldControl?.dirty;
|
|
121
|
+
protected readonly _spartanInvalid = this._fieldControl?.spartanInvalid;
|
|
122
|
+
|
|
104
123
|
constructor() {
|
|
105
124
|
classes(() => 'group/native-select relative w-fit has-[select:disabled]:opacity-50');
|
|
106
125
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { Directive } from '@angular/core';
|
|
1
|
+
import { computed, Directive, inject, input } from '@angular/core';
|
|
2
|
+
import { BrnFieldControlDescribedBy } from '@spartan-ng/brain/field';
|
|
2
3
|
import { BrnRadioGroup } from '@spartan-ng/brain/radio-group';
|
|
3
4
|
import { classes } from '<%- importAlias %>/utils';
|
|
5
|
+
import type { ClassValue } from 'clsx';
|
|
4
6
|
|
|
5
7
|
@Directive({
|
|
6
8
|
selector: '[hlmRadioGroup],hlm-radio-group',
|
|
@@ -10,13 +12,27 @@ import { classes } from '<%- importAlias %>/utils';
|
|
|
10
12
|
inputs: ['name', 'value', 'disabled', 'required'],
|
|
11
13
|
outputs: ['valueChange'],
|
|
12
14
|
},
|
|
15
|
+
BrnFieldControlDescribedBy,
|
|
13
16
|
],
|
|
14
17
|
host: {
|
|
15
18
|
'data-slot': 'radio-group',
|
|
19
|
+
'[attr.aria-invalid]': '_ariaInvalid() ? "true" : null',
|
|
20
|
+
'[attr.data-invalid]': '_ariaInvalid() ? "true" : null',
|
|
21
|
+
'[attr.data-dirty]': '_dirty() ? "true" : null',
|
|
22
|
+
'[attr.data-touched]': '_touched() ? "true" : null',
|
|
16
23
|
},
|
|
17
24
|
})
|
|
18
25
|
export class HlmRadioGroup {
|
|
26
|
+
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
27
|
+
private readonly _brnRadioGroup = inject(BrnRadioGroup);
|
|
28
|
+
protected readonly _ariaInvalid = computed(() => this._brnRadioGroup.controlState?.()?.invalid);
|
|
29
|
+
|
|
30
|
+
protected readonly _touched = computed(() => this._brnRadioGroup.controlState?.()?.touched);
|
|
31
|
+
protected readonly _dirty = computed(() => this._brnRadioGroup.controlState?.()?.dirty);
|
|
32
|
+
|
|
33
|
+
protected readonly _errorState = computed(() => this._brnRadioGroup.controlState?.()?.spartanInvalid);
|
|
34
|
+
|
|
19
35
|
constructor() {
|
|
20
|
-
classes(() => 'grid gap-3');
|
|
36
|
+
classes(() => ['grid gap-3', this.userClass(), this._errorState() ? 'data-[invalid=true]:text-destructive' : '']);
|
|
21
37
|
}
|
|
22
38
|
}
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
PLATFORM_ID,
|
|
15
15
|
Renderer2,
|
|
16
16
|
} from '@angular/core';
|
|
17
|
-
import { BrnRadio, type BrnRadioChange } from '@spartan-ng/brain/radio-group';
|
|
17
|
+
import { BrnRadio, BrnRadioGroup, type BrnRadioChange } from '@spartan-ng/brain/radio-group';
|
|
18
18
|
import { hlm } from '<%- importAlias %>/utils';
|
|
19
19
|
import type { ClassValue } from 'clsx';
|
|
20
20
|
|
|
@@ -37,6 +37,11 @@ import type { ClassValue } from 'clsx';
|
|
|
37
37
|
[value]="value()"
|
|
38
38
|
[required]="required()"
|
|
39
39
|
[disabled]="disabled()"
|
|
40
|
+
[attr.aria-invalid]="_ariaInvalid() ? 'true' : null"
|
|
41
|
+
[attr.data-invalid]="_ariaInvalid() ? 'true' : null"
|
|
42
|
+
[attr.data-dirty]="_dirty() ? 'true' : null"
|
|
43
|
+
[attr.data-touched]="_touched() ? 'true' : null"
|
|
44
|
+
[attr.data-matches-spartan-invalid]="_groupSpartanInvalid() ? 'true' : null"
|
|
40
45
|
[aria-label]="ariaLabel()"
|
|
41
46
|
[aria-labelledby]="ariaLabelledby()"
|
|
42
47
|
[aria-describedby]="ariaDescribedby()"
|
|
@@ -52,6 +57,15 @@ export class HlmRadio<T = unknown> {
|
|
|
52
57
|
private readonly _renderer = inject(Renderer2);
|
|
53
58
|
private readonly _elementRef = inject(ElementRef);
|
|
54
59
|
private readonly _isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
|
|
60
|
+
private readonly _radioGroup = inject(BrnRadioGroup, { optional: true });
|
|
61
|
+
|
|
62
|
+
protected readonly _ariaInvalid = computed(() => this._radioGroup?.controlState?.()?.invalid);
|
|
63
|
+
|
|
64
|
+
protected readonly _touched = computed(() => this._radioGroup?.controlState?.()?.touched);
|
|
65
|
+
protected readonly _dirty = computed(() => this._radioGroup?.controlState?.()?.dirty);
|
|
66
|
+
protected readonly _groupSpartanInvalid = computed(() => this._radioGroup?.controlState?.()?.spartanInvalid);
|
|
67
|
+
|
|
68
|
+
protected readonly _errorStateClass = computed(() => (this._groupSpartanInvalid() ? 'text-destructive' : ''));
|
|
55
69
|
|
|
56
70
|
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
57
71
|
protected readonly _computedClass = computed(() =>
|
|
@@ -59,6 +73,7 @@ export class HlmRadio<T = unknown> {
|
|
|
59
73
|
'group relative flex items-center gap-x-3',
|
|
60
74
|
'data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50',
|
|
61
75
|
this.userClass(),
|
|
76
|
+
this._errorStateClass(),
|
|
62
77
|
),
|
|
63
78
|
);
|
|
64
79
|
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
|
2
2
|
import { NgIcon, provideIcons } from '@ng-icons/core';
|
|
3
3
|
import { lucideChevronDown } from '@ng-icons/lucide';
|
|
4
|
+
import { BrnFieldControlDescribedBy } from '@spartan-ng/brain/field';
|
|
4
5
|
import { BrnSelectTrigger, BrnSelectTriggerWrapper } from '@spartan-ng/brain/select';
|
|
5
6
|
import { hlm } from '<%- importAlias %>/utils';
|
|
6
7
|
import type { ClassValue } from 'clsx';
|
|
7
8
|
|
|
8
9
|
@Component({
|
|
9
10
|
selector: 'hlm-select-trigger',
|
|
10
|
-
imports: [NgIcon, BrnSelectTrigger],
|
|
11
|
+
imports: [NgIcon, BrnSelectTrigger, BrnFieldControlDescribedBy],
|
|
11
12
|
providers: [provideIcons({ lucideChevronDown })],
|
|
12
13
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
13
14
|
hostDirectives: [BrnSelectTriggerWrapper],
|
|
14
15
|
template: `
|
|
15
16
|
<button
|
|
16
17
|
brnSelectTrigger
|
|
18
|
+
brnFieldControlDescribedBy
|
|
17
19
|
[id]="buttonId()"
|
|
18
20
|
[class]="_computedClass()"
|
|
19
21
|
[attr.data-size]="size()"
|
|
@@ -30,7 +32,8 @@ export class HlmSelectTrigger {
|
|
|
30
32
|
public readonly userClass = input<ClassValue>('', { alias: 'class' });
|
|
31
33
|
protected readonly _computedClass = computed(() =>
|
|
32
34
|
hlm(
|
|
33
|
-
"border-input data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/50
|
|
35
|
+
"border-input data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/50 flex w-full items-center justify-between gap-1.5 rounded-md border bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-3 disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 [&_ng-icon]:pointer-events-none [&_ng-icon]:shrink-0 [&_ng-icon:not([class*='text-'])]:text-base",
|
|
36
|
+
'data-[matches-spartan-invalid=true]:ring-destructive/20 dark:data-[matches-spartan-invalid=true]:ring-destructive/40 data-[matches-spartan-invalid=true]:border-destructive dark:data-[matches-spartan-invalid=true]:border-destructive/50 data-[matches-spartan-invalid=true]:ring-3',
|
|
34
37
|
this.userClass(),
|
|
35
38
|
),
|
|
36
39
|
);
|
|
@@ -72,9 +72,8 @@ export class HlmSlider {
|
|
|
72
72
|
protected readonly _slider = injectBrnSlider();
|
|
73
73
|
|
|
74
74
|
constructor() {
|
|
75
|
-
classes(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
);
|
|
75
|
+
classes(() => [
|
|
76
|
+
'group flex w-full touch-none flex-col select-none data-vertical:h-full data-vertical:min-h-40 data-vertical:w-auto data-vertical:flex-row data-[disabled]:pointer-events-none data-[disabled]:opacity-50',
|
|
77
|
+
]);
|
|
79
78
|
}
|
|
80
79
|
}
|
|
@@ -1,29 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
type DoCheck,
|
|
5
|
-
effect,
|
|
6
|
-
forwardRef,
|
|
7
|
-
inject,
|
|
8
|
-
Injector,
|
|
9
|
-
input,
|
|
10
|
-
linkedSignal,
|
|
11
|
-
signal,
|
|
12
|
-
untracked,
|
|
13
|
-
} from '@angular/core';
|
|
14
|
-
import { FormGroupDirective, NgControl, NgForm } from '@angular/forms';
|
|
15
|
-
import { BrnFormFieldControl } from '@spartan-ng/brain/form-field';
|
|
16
|
-
import { ErrorStateMatcher, ErrorStateTracker } from '@spartan-ng/brain/forms';
|
|
1
|
+
import { Directive, input } from '@angular/core';
|
|
2
|
+
import { BrnFieldControlDescribedBy } from '@spartan-ng/brain/field';
|
|
3
|
+
import { BrnTextarea } from '@spartan-ng/brain/textarea';
|
|
17
4
|
import { classes } from '<%- importAlias %>/utils';
|
|
18
5
|
import { cva, type VariantProps } from 'class-variance-authority';
|
|
19
|
-
import { ClassValue } from 'clsx';
|
|
20
6
|
|
|
21
7
|
export const textareaVariants = cva(
|
|
22
8
|
'border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 dark:bg-input/30 flex [field-sizing:content] min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
|
23
9
|
{
|
|
24
10
|
variants: {
|
|
25
11
|
error: {
|
|
26
|
-
auto: '[
|
|
12
|
+
auto: 'data-[matches-spartan-invalid=true]:border-destructive data-[matches-spartan-invalid=true]:ring-destructive/20 dark:data-[matches-spartan-invalid=true]:ring-destructive/40',
|
|
27
13
|
true: 'border-destructive focus-visible:border-destructive focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40',
|
|
28
14
|
},
|
|
29
15
|
},
|
|
@@ -36,65 +22,18 @@ type TextareaVariants = VariantProps<typeof textareaVariants>;
|
|
|
36
22
|
|
|
37
23
|
@Directive({
|
|
38
24
|
selector: '[hlmTextarea]',
|
|
39
|
-
|
|
40
|
-
{
|
|
41
|
-
provide: BrnFormFieldControl,
|
|
42
|
-
useExisting: forwardRef(() => HlmTextarea),
|
|
43
|
-
},
|
|
44
|
-
],
|
|
25
|
+
hostDirectives: [{ directive: BrnTextarea, inputs: ['id'] }, BrnFieldControlDescribedBy],
|
|
45
26
|
host: {
|
|
46
27
|
'data-slot': 'textarea',
|
|
47
28
|
},
|
|
48
29
|
})
|
|
49
|
-
export class HlmTextarea
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
private readonly _errorStateTracker: ErrorStateTracker;
|
|
54
|
-
|
|
55
|
-
private readonly _defaultErrorStateMatcher = inject(ErrorStateMatcher);
|
|
56
|
-
private readonly _parentForm = inject(NgForm, { optional: true });
|
|
57
|
-
private readonly _parentFormGroup = inject(FormGroupDirective, { optional: true });
|
|
58
|
-
|
|
30
|
+
export class HlmTextarea {
|
|
31
|
+
/** Controls the error visual state of the textarea.
|
|
32
|
+
* Defaults to 'auto', which infers the state from the associated form control.
|
|
33
|
+
*/
|
|
59
34
|
public readonly error = input<TextareaVariants['error']>('auto');
|
|
60
35
|
|
|
61
|
-
protected readonly _state = linkedSignal(() => ({ error: this.error() }));
|
|
62
|
-
|
|
63
|
-
public readonly ngControl: NgControl | null = this._injector.get(NgControl, null);
|
|
64
|
-
|
|
65
|
-
public readonly errorState = computed(() => this._errorStateTracker.errorState());
|
|
66
|
-
|
|
67
36
|
constructor() {
|
|
68
|
-
classes(() =>
|
|
69
|
-
|
|
70
|
-
this._errorStateTracker = new ErrorStateTracker(
|
|
71
|
-
this._defaultErrorStateMatcher,
|
|
72
|
-
this.ngControl,
|
|
73
|
-
this._parentFormGroup,
|
|
74
|
-
this._parentForm,
|
|
75
|
-
);
|
|
76
|
-
|
|
77
|
-
effect(() => {
|
|
78
|
-
const error = this._errorStateTracker.errorState();
|
|
79
|
-
untracked(() => {
|
|
80
|
-
if (this.ngControl) {
|
|
81
|
-
const shouldShowError = error && this.ngControl.invalid && (this.ngControl.touched || this.ngControl.dirty);
|
|
82
|
-
this._errorStateTracker.errorState.set(shouldShowError ? true : false);
|
|
83
|
-
this.setError(shouldShowError ? true : 'auto');
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
ngDoCheck() {
|
|
90
|
-
this._errorStateTracker.updateErrorState();
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
public setError(error: TextareaVariants['error']): void {
|
|
94
|
-
this._state.set({ error });
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
public setClass(classes: string): void {
|
|
98
|
-
this._additionalClasses.set(classes);
|
|
37
|
+
classes(() => textareaVariants({ error: this.error() }));
|
|
99
38
|
}
|
|
100
39
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"primitive-deps.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/generators/ui/primitive-deps.ts"],"names":[],"mappings":";;;AAEa,QAAA,qBAAqB,GAAmC;IACpE,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;IACnC,cAAc,EAAE,CAAC,OAAO,CAAC;IACzB,YAAY,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC;IACzD,MAAM,EAAE,CAAC,OAAO,CAAC;IACjB,KAAK,EAAE,CAAC,OAAO,CAAC;IAChB,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IAC7B,MAAM,EAAE,CAAC,OAAO,CAAC;IACjB,cAAc,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC;IACnC,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC;IAC/C,IAAI,EAAE,CAAC,OAAO,CAAC;IACf,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC;IACrC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IAC3B,WAAW,EAAE,CAAC,OAAO,CAAC;IACtB,QAAQ,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,CAAC;IACpD,OAAO,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC;IACpC,cAAc,EAAE,CAAC,OAAO,EAAE,eAAe,CAAC;IAC1C,aAAa,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC;IACvD,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC;IAClC,KAAK,EAAE,CAAC,OAAO,CAAC;IAChB,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC;IACtC,YAAY,EAAE,CAAC,OAAO,CAAC;IACvB,
|
|
1
|
+
{"version":3,"file":"primitive-deps.js","sourceRoot":"","sources":["../../../../../../libs/cli/src/generators/ui/primitive-deps.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export type Primitive = 'accordion' | 'alert' | 'alert-dialog' | 'aspect-ratio' | 'autocomplete' | 'avatar' | 'badge' | 'breadcrumb' | 'button' | 'button-group' | 'calendar' | 'card' | 'carousel' | 'checkbox' | 'collapsible' | 'combobox' | 'command' | 'context-menu' | 'date-picker' | 'dialog' | 'dropdown-menu' | 'empty' | 'field' | '
|
|
1
|
+
export type Primitive = 'accordion' | 'alert' | 'alert-dialog' | 'aspect-ratio' | 'autocomplete' | 'avatar' | 'badge' | 'breadcrumb' | 'button' | 'button-group' | 'calendar' | 'card' | 'carousel' | 'checkbox' | 'collapsible' | 'combobox' | 'command' | 'context-menu' | 'date-picker' | 'dialog' | 'dropdown-menu' | 'empty' | 'field' | 'hover-card' | 'icon' | 'input' | 'input-group' | 'input-otp' | 'item' | 'kbd' | 'label' | 'menubar' | 'native-select' | 'navigation-menu' | 'pagination' | 'popover' | 'progress' | 'radio-group' | 'resizable' | 'scroll-area' | 'select' | 'separator' | 'sheet' | 'sidebar' | 'skeleton' | 'slider' | 'sonner' | 'spinner' | 'switch' | 'table' | 'tabs' | 'textarea' | 'toggle' | 'toggle-group' | 'tooltip' | 'typography' | 'utils';
|