@egose/shadcn-theme-ng 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/accordion/README.md +405 -2
- package/alert/README.md +372 -2
- package/alert-dialog/README.md +471 -5
- package/aspect-ratio/README.md +272 -5
- package/autocomplete/README.md +502 -2
- package/autocomplete/fesm2022/autocomplete.mjs +1 -1
- package/avatar/README.md +357 -5
- package/badge/README.md +318 -2
- package/basic-alert/README.md +353 -2
- package/breadcrumb/README.md +406 -5
- package/button/README.md +482 -2
- package/button/fesm2022/button.mjs +85 -107
- package/button/types/button.d.ts +5 -8
- package/button-group/README.md +318 -5
- package/calendar/README.md +357 -2
- package/card/README.md +331 -5
- package/carousel/README.md +333 -5
- package/carousel/fesm2022/carousel.mjs +4 -1
- package/checkbox/README.md +320 -2
- package/checkbox/fesm2022/checkbox.mjs +6 -7
- package/checkbox/types/checkbox.d.ts +1 -1
- package/collapsible/README.md +332 -5
- package/combobox/README.md +507 -5
- package/combobox/fesm2022/combobox.mjs +5 -2
- package/command/README.md +435 -5
- package/confirmation-dialog/README.md +301 -2
- package/context-menu/README.md +366 -5
- package/date-picker/README.md +469 -2
- package/date-picker/fesm2022/date-picker.mjs +150 -32
- package/date-picker/types/date-picker.d.ts +102 -9
- package/dialog/README.md +448 -2
- package/drawer/README.md +395 -5
- package/dropdown-menu/README.md +417 -5
- package/empty/README.md +329 -5
- package/field/README.md +385 -5
- package/form-autocomplete/README.md +177 -0
- package/form-autocomplete/fesm2022/form-autocomplete.mjs +125 -0
- package/form-autocomplete/package.json +24 -0
- package/form-autocomplete/types/form-autocomplete.d.ts +61 -0
- package/form-checkbox/README.md +322 -2
- package/form-checkbox/fesm2022/form-checkbox.mjs +22 -9
- package/form-checkbox/types/form-checkbox.d.ts +23 -4
- package/form-combobox/README.md +202 -0
- package/form-combobox/fesm2022/form-combobox.mjs +147 -0
- package/form-combobox/package.json +24 -0
- package/form-combobox/types/form-combobox.d.ts +73 -0
- package/form-date-picker/README.md +348 -2
- package/form-date-picker/fesm2022/form-date-picker.mjs +38 -12
- package/form-date-picker/types/form-date-picker.d.ts +17 -1
- package/form-date-picker-multi/README.md +191 -0
- package/form-date-picker-multi/fesm2022/form-date-picker-multi.mjs +129 -0
- package/form-date-picker-multi/package.json +24 -0
- package/form-date-picker-multi/types/form-date-picker-multi.d.ts +58 -0
- package/form-date-range-picker/README.md +253 -0
- package/form-date-range-picker/fesm2022/form-date-range-picker.mjs +130 -0
- package/form-date-range-picker/package.json +24 -0
- package/form-date-range-picker/types/form-date-range-picker.d.ts +55 -0
- package/form-field/README.md +356 -2
- package/form-field-simple/README.md +340 -2
- package/form-input-otp/README.md +194 -0
- package/form-input-otp/fesm2022/form-input-otp.mjs +106 -0
- package/form-input-otp/package.json +24 -0
- package/form-input-otp/types/form-input-otp.d.ts +58 -0
- package/form-month-year-picker/README.md +188 -0
- package/form-month-year-picker/fesm2022/form-month-year-picker.mjs +125 -0
- package/form-month-year-picker/package.json +24 -0
- package/form-month-year-picker/types/form-month-year-picker.d.ts +53 -0
- package/form-native-select/README.md +205 -0
- package/form-native-select/fesm2022/form-native-select.mjs +103 -0
- package/form-native-select/package.json +24 -0
- package/form-native-select/types/form-native-select.d.ts +57 -0
- package/form-phone-input/README.md +188 -0
- package/form-phone-input/fesm2022/form-phone-input.mjs +113 -0
- package/form-phone-input/package.json +24 -0
- package/form-phone-input/types/form-phone-input.d.ts +58 -0
- package/form-radio-group/README.md +198 -0
- package/form-radio-group/fesm2022/form-radio-group.mjs +111 -0
- package/form-radio-group/package.json +24 -0
- package/form-radio-group/types/form-radio-group.d.ts +63 -0
- package/form-searchable-multiselect/README.md +371 -2
- package/form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs +19 -10
- package/form-searchable-multiselect/types/form-searchable-multiselect.d.ts +18 -1
- package/form-select/README.md +360 -2
- package/form-select/fesm2022/form-select.mjs +20 -11
- package/form-select/types/form-select.d.ts +18 -1
- package/form-slider/README.md +182 -0
- package/form-slider/fesm2022/form-slider.mjs +106 -0
- package/form-slider/package.json +24 -0
- package/form-slider/types/form-slider.d.ts +60 -0
- package/form-switch/README.md +173 -0
- package/form-switch/fesm2022/form-switch.mjs +100 -0
- package/form-switch/package.json +24 -0
- package/form-switch/types/form-switch.d.ts +50 -0
- package/form-text-input/README.md +381 -2
- package/form-text-input/fesm2022/form-text-input.mjs +19 -10
- package/form-text-input/types/form-text-input.d.ts +18 -1
- package/form-textarea/README.md +357 -2
- package/form-textarea/fesm2022/form-textarea.mjs +19 -10
- package/form-textarea/types/form-textarea.d.ts +18 -1
- package/form-toggle/README.md +186 -0
- package/form-toggle/fesm2022/form-toggle.mjs +159 -0
- package/form-toggle/package.json +24 -0
- package/form-toggle/types/form-toggle.d.ts +82 -0
- package/form-toggle-group/README.md +176 -0
- package/form-toggle-group/fesm2022/form-toggle-group.mjs +116 -0
- package/form-toggle-group/package.json +24 -0
- package/form-toggle-group/types/form-toggle-group.d.ts +65 -0
- package/hover-card/README.md +256 -5
- package/icon/README.md +239 -2
- package/input/README.md +269 -2
- package/input-group/README.md +335 -5
- package/input-group/fesm2022/input-group.mjs +22 -12
- package/input-group/types/input-group.d.ts +4 -1
- package/input-otp/README.md +375 -5
- package/item/README.md +385 -5
- package/item/fesm2022/item.mjs +3 -3
- package/kbd/README.md +291 -5
- package/label/README.md +272 -2
- package/layout-simple/README.md +193 -2
- package/layout-simple/fesm2022/layout-simple.mjs +472 -236
- package/layout-simple/types/layout-simple.d.ts +174 -137
- package/menu/README.md +417 -2
- package/menubar/README.md +343 -5
- package/native-select/README.md +323 -5
- package/native-select/fesm2022/native-select.mjs +18 -6
- package/native-select/types/native-select.d.ts +7 -2
- package/navigation-menu/README.md +369 -5
- package/package.json +57 -1
- package/pagination/README.md +388 -5
- package/phone-input/README.md +114 -0
- package/phone-input/fesm2022/phone-input.mjs +191 -0
- package/phone-input/package.json +24 -0
- package/phone-input/types/phone-input.d.ts +67 -0
- package/popover/README.md +331 -2
- package/progress/README.md +311 -5
- package/radio-group/README.md +364 -2
- package/radio-group/fesm2022/radio-group.mjs +5 -1
- package/resizable/README.md +269 -5
- package/scroll-area/README.md +233 -5
- package/searchable-multiselect/README.md +323 -2
- package/select/README.md +437 -2
- package/separator/README.md +222 -2
- package/sheet/README.md +311 -2
- package/sidebar/README.md +457 -5
- package/skeleton/README.md +217 -5
- package/slider/README.md +273 -5
- package/slider/fesm2022/slider.mjs +3 -3
- package/sonner/README.md +346 -2
- package/spinner/README.md +284 -2
- package/switch/README.md +310 -2
- package/switch/fesm2022/switch.mjs +7 -5
- package/switch/types/switch.d.ts +2 -1
- package/table/README.md +423 -5
- package/tabs/README.md +411 -2
- package/tabs/fesm2022/tabs.mjs +2 -2
- package/textarea/README.md +282 -5
- package/toggle/README.md +270 -5
- package/toggle-group/README.md +340 -5
- package/tooltip/README.md +269 -2
- package/typography/README.md +271 -5
- package/utils/README.md +303 -2
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { InjectionToken, inject, input, computed, Component } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/forms';
|
|
4
|
+
import { FormGroupDirective, ReactiveFormsModule, ControlContainer } from '@angular/forms';
|
|
5
|
+
import { HlmFormIdGenerator, HlmFormField, HlmError, HlmHint } from '@egose/shadcn-theme-ng/form-field';
|
|
6
|
+
import { HlmLabel } from '@egose/shadcn-theme-ng/label';
|
|
7
|
+
import { HlmAutocomplete, HlmAutocompleteContent, HlmAutocompleteEmpty, HlmAutocompleteGroup, HlmAutocompleteInput, HlmAutocompleteItem, HlmAutocompleteList, HlmAutocompleteLabel } from '@egose/shadcn-theme-ng/autocomplete';
|
|
8
|
+
import { hlm } from '@egose/shadcn-theme-ng/utils';
|
|
9
|
+
|
|
10
|
+
const EgFormAutocompleteConfigToken = new InjectionToken('EgFormAutocompleteConfig');
|
|
11
|
+
function provideEgFormAutocompleteConfig(config) {
|
|
12
|
+
return { provide: EgFormAutocompleteConfigToken, useValue: { ...config } };
|
|
13
|
+
}
|
|
14
|
+
function injectEgFormAutocompleteConfig() {
|
|
15
|
+
return inject(EgFormAutocompleteConfigToken, { optional: true }) ?? {};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class EgFormAutocomplete {
|
|
19
|
+
formGroupDirective = inject(FormGroupDirective);
|
|
20
|
+
generatedId = inject(HlmFormIdGenerator).generate('eg-form-autocomplete');
|
|
21
|
+
_config = injectEgFormAutocompleteConfig();
|
|
22
|
+
label = input(undefined, /* @ts-ignore */
|
|
23
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
24
|
+
controlId = input(undefined, /* @ts-ignore */
|
|
25
|
+
...(ngDevMode ? [{ debugName: "controlId" }] : /* istanbul ignore next */ []));
|
|
26
|
+
controlName = input('', /* @ts-ignore */
|
|
27
|
+
...(ngDevMode ? [{ debugName: "controlName" }] : /* istanbul ignore next */ []));
|
|
28
|
+
error = input(undefined, /* @ts-ignore */
|
|
29
|
+
...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
|
30
|
+
hint = input(undefined, /* @ts-ignore */
|
|
31
|
+
...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
32
|
+
id = input(undefined, /* @ts-ignore */
|
|
33
|
+
...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
34
|
+
placeholder = input('Type to search…', /* @ts-ignore */
|
|
35
|
+
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
36
|
+
emptyText = input('No result.', /* @ts-ignore */
|
|
37
|
+
...(ngDevMode ? [{ debugName: "emptyText" }] : /* istanbul ignore next */ []));
|
|
38
|
+
disabled = input(false, /* @ts-ignore */
|
|
39
|
+
...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
|
|
40
|
+
required = input(false, /* @ts-ignore */
|
|
41
|
+
...(ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []));
|
|
42
|
+
options = input([], /* @ts-ignore */
|
|
43
|
+
...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
44
|
+
effectiveId = computed(() => this.controlId() || this.id() || this.generatedId, /* @ts-ignore */
|
|
45
|
+
...(ngDevMode ? [{ debugName: "effectiveId" }] : /* istanbul ignore next */ []));
|
|
46
|
+
errorId = computed(() => `${this.effectiveId()}-error`, /* @ts-ignore */
|
|
47
|
+
...(ngDevMode ? [{ debugName: "errorId" }] : /* istanbul ignore next */ []));
|
|
48
|
+
hintId = computed(() => `${this.effectiveId()}-hint`, /* @ts-ignore */
|
|
49
|
+
...(ngDevMode ? [{ debugName: "hintId" }] : /* istanbul ignore next */ []));
|
|
50
|
+
/**
|
|
51
|
+
* Combined lock for the brain `linkedSignal`-based disabled state: the raw
|
|
52
|
+
* input write always carries the resolved value, so a same-pass
|
|
53
|
+
* wrapper-toggle + `control.disable()` cannot clobber CVA state.
|
|
54
|
+
*/
|
|
55
|
+
effectiveDisabled() {
|
|
56
|
+
return this.disabled() || !!this.formGroupDirective.form.get(this.controlName())?.disabled;
|
|
57
|
+
}
|
|
58
|
+
// Styling
|
|
59
|
+
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
60
|
+
labelClass = input('', /* @ts-ignore */
|
|
61
|
+
...(ngDevMode ? [{ debugName: "labelClass" }] : /* istanbul ignore next */ []));
|
|
62
|
+
controlClass = input('', /* @ts-ignore */
|
|
63
|
+
...(ngDevMode ? [{ debugName: "controlClass" }] : /* istanbul ignore next */ []));
|
|
64
|
+
inputClass = input('', /* @ts-ignore */
|
|
65
|
+
...(ngDevMode ? [{ debugName: "inputClass" }] : /* istanbul ignore next */ []));
|
|
66
|
+
errorClass = input('', /* @ts-ignore */
|
|
67
|
+
...(ngDevMode ? [{ debugName: "errorClass" }] : /* istanbul ignore next */ []));
|
|
68
|
+
hintClass = input('', /* @ts-ignore */
|
|
69
|
+
...(ngDevMode ? [{ debugName: "hintClass" }] : /* istanbul ignore next */ []));
|
|
70
|
+
// Computed classes (library base < global config < per-instance).
|
|
71
|
+
// NOTE: the autocomplete input exposes no aria-describedby, so error/hint
|
|
72
|
+
// ids render without an input-level describedby link.
|
|
73
|
+
$userClass = computed(() => hlm("w-full", this.userClass()), /* @ts-ignore */
|
|
74
|
+
...(ngDevMode ? [{ debugName: "$userClass" }] : /* istanbul ignore next */ []));
|
|
75
|
+
$labelClass = computed(() => hlm("mb-1", this._config.labelClass, this.labelClass()), /* @ts-ignore */
|
|
76
|
+
...(ngDevMode ? [{ debugName: "$labelClass" }] : /* istanbul ignore next */ []));
|
|
77
|
+
$controlClass = computed(() => hlm(this._config.controlClass, this.controlClass()), /* @ts-ignore */
|
|
78
|
+
...(ngDevMode ? [{ debugName: "$controlClass" }] : /* istanbul ignore next */ []));
|
|
79
|
+
$inputClass = computed(() => hlm(this._config.inputClass, this.inputClass()), /* @ts-ignore */
|
|
80
|
+
...(ngDevMode ? [{ debugName: "$inputClass" }] : /* istanbul ignore next */ []));
|
|
81
|
+
$errorClass = computed(() => hlm("mt-0", this._config.errorClass, this.errorClass()), /* @ts-ignore */
|
|
82
|
+
...(ngDevMode ? [{ debugName: "$errorClass" }] : /* istanbul ignore next */ []));
|
|
83
|
+
$hintClass = computed(() => hlm("mt-0", this._config.hintClass, this.hintClass()), /* @ts-ignore */
|
|
84
|
+
...(ngDevMode ? [{ debugName: "$hintClass" }] : /* istanbul ignore next */ []));
|
|
85
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormAutocomplete, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
86
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormAutocomplete, isStandalone: true, selector: "eg-form-autocomplete", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, controlId: { classPropertyName: "controlId", publicName: "controlId", isSignal: true, isRequired: false, transformFunction: null }, controlName: { classPropertyName: "controlName", publicName: "controlName", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, labelClass: { classPropertyName: "labelClass", publicName: "labelClass", isSignal: true, isRequired: false, transformFunction: null }, controlClass: { classPropertyName: "controlClass", publicName: "controlClass", isSignal: true, isRequired: false, transformFunction: null }, inputClass: { classPropertyName: "inputClass", publicName: "inputClass", isSignal: true, isRequired: false, transformFunction: null }, errorClass: { classPropertyName: "errorClass", publicName: "errorClass", isSignal: true, isRequired: false, transformFunction: null }, hintClass: { classPropertyName: "hintClass", publicName: "hintClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "$userClass()" } }, providers: [{ provide: ControlContainer, useExisting: FormGroupDirective }], ngImport: i0, template: "\n @let lbl = label();\n @let cnm = controlName();\n @let err = error();\n @let hnt = hint();\n @let rqrd = required();\n\n <hlm-form-field>\n @if (lbl) {\n <label hlmLabel [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div hlmAutocomplete [formControlName]=\"cnm\" [disabled]=\"effectiveDisabled()\" [class]=\"$controlClass()\">\n <hlm-autocomplete-input [inputId]=\"effectiveId()\" [placeholder]=\"placeholder()\" [class]=\"$inputClass()\" />\n <hlm-autocomplete-content>\n <div hlmAutocompleteList>\n <div hlmAutocompleteGroup>\n @for (option of options(); track option) {\n <hlm-autocomplete-item [value]=\"option\">{{ option }}</hlm-autocomplete-item>\n }\n </div>\n </div>\n <div hlmAutocompleteEmpty>{{ emptyText() }}</div>\n </hlm-autocomplete-content>\n </div>\n\n @if (err) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ err }}\n </hlm-error>\n }\n\n @if (hnt) {\n <hlm-hint [id]=\"hintId()\" [class]=\"$hintClass()\">\n {{ hnt }}\n </hlm-hint>\n }\n </hlm-form-field>\n ", isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: HlmFormField, selector: "hlm-form-field", inputs: ["class"] }, { kind: "directive", type: HlmError, selector: "hlm-error", inputs: ["class"] }, { kind: "directive", type: HlmHint, selector: "hlm-hint", inputs: ["class"] }, { kind: "directive", type: HlmLabel, selector: "[hlmLabel]", inputs: ["class"] }, { kind: "directive", type: HlmAutocomplete, selector: "[hlmAutocomplete],hlm-autocomplete" }, { kind: "directive", type: HlmAutocompleteContent, selector: "[hlmAutocompleteContent],hlm-autocomplete-content" }, { kind: "directive", type: HlmAutocompleteEmpty, selector: "[hlmAutocompleteEmpty],hlm-autocomplete-empty" }, { kind: "directive", type: HlmAutocompleteGroup, selector: "[hlmAutocompleteGroup]" }, { kind: "component", type: HlmAutocompleteInput, selector: "hlm-autocomplete-input", inputs: ["inputId", "placeholder", "showSearch", "showClear", "forceInvalid", "aria-invalid"] }, { kind: "component", type: HlmAutocompleteItem, selector: "hlm-autocomplete-item" }, { kind: "directive", type: HlmAutocompleteList, selector: "[hlmAutocompleteList]" }] });
|
|
87
|
+
}
|
|
88
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormAutocomplete, decorators: [{
|
|
89
|
+
type: Component,
|
|
90
|
+
args: [{
|
|
91
|
+
selector: 'eg-form-autocomplete',
|
|
92
|
+
standalone: true,
|
|
93
|
+
host: {
|
|
94
|
+
'[class]': '$userClass()',
|
|
95
|
+
},
|
|
96
|
+
imports: [
|
|
97
|
+
ReactiveFormsModule,
|
|
98
|
+
HlmFormField,
|
|
99
|
+
HlmError,
|
|
100
|
+
HlmHint,
|
|
101
|
+
HlmLabel,
|
|
102
|
+
HlmAutocomplete,
|
|
103
|
+
HlmAutocompleteContent,
|
|
104
|
+
HlmAutocompleteEmpty,
|
|
105
|
+
HlmAutocompleteGroup,
|
|
106
|
+
HlmAutocompleteInput,
|
|
107
|
+
HlmAutocompleteItem,
|
|
108
|
+
HlmAutocompleteLabel,
|
|
109
|
+
HlmAutocompleteList,
|
|
110
|
+
],
|
|
111
|
+
providers: [{ provide: ControlContainer, useExisting: FormGroupDirective }],
|
|
112
|
+
template: "\n @let lbl = label();\n @let cnm = controlName();\n @let err = error();\n @let hnt = hint();\n @let rqrd = required();\n\n <hlm-form-field>\n @if (lbl) {\n <label hlmLabel [for]=\"effectiveId()\" [class]=\"$labelClass()\"\n >{{ lbl }}\n @if (rqrd) {\n <span class=\"text-red-500\">*</span>\n }\n </label>\n }\n\n <div hlmAutocomplete [formControlName]=\"cnm\" [disabled]=\"effectiveDisabled()\" [class]=\"$controlClass()\">\n <hlm-autocomplete-input [inputId]=\"effectiveId()\" [placeholder]=\"placeholder()\" [class]=\"$inputClass()\" />\n <hlm-autocomplete-content>\n <div hlmAutocompleteList>\n <div hlmAutocompleteGroup>\n @for (option of options(); track option) {\n <hlm-autocomplete-item [value]=\"option\">{{ option }}</hlm-autocomplete-item>\n }\n </div>\n </div>\n <div hlmAutocompleteEmpty>{{ emptyText() }}</div>\n </hlm-autocomplete-content>\n </div>\n\n @if (err) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ err }}\n </hlm-error>\n }\n\n @if (hnt) {\n <hlm-hint [id]=\"hintId()\" [class]=\"$hintClass()\">\n {{ hnt }}\n </hlm-hint>\n }\n </hlm-form-field>\n ",
|
|
113
|
+
}]
|
|
114
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], controlId: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlId", required: false }] }], controlName: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlName", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], emptyText: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyText", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], labelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelClass", required: false }] }], controlClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlClass", required: false }] }], inputClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClass", required: false }] }], errorClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorClass", required: false }] }], hintClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "hintClass", required: false }] }] } });
|
|
115
|
+
|
|
116
|
+
/*
|
|
117
|
+
* Public API Surface of form-autocomplete
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Generated bundle index. Do not edit.
|
|
122
|
+
*/
|
|
123
|
+
|
|
124
|
+
export { EgFormAutocomplete, injectEgFormAutocompleteConfig, provideEgFormAutocompleteConfig };
|
|
125
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "form-autocomplete",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"peerDependencies": {
|
|
5
|
+
"@angular/common": "^20.3.0 || ^22.0.0",
|
|
6
|
+
"@angular/core": "^20.3.0 || ^22.0.0"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"tslib": "^2.3.0"
|
|
10
|
+
},
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"module": "fesm2022/form-autocomplete.mjs",
|
|
13
|
+
"typings": "types/form-autocomplete.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
"./package.json": {
|
|
16
|
+
"default": "./package.json"
|
|
17
|
+
},
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./types/form-autocomplete.d.ts",
|
|
20
|
+
"default": "./fesm2022/form-autocomplete.mjs"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"type": "module"
|
|
24
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { ValueProvider } from '@angular/core';
|
|
3
|
+
import { ClassValue } from 'clsx';
|
|
4
|
+
|
|
5
|
+
declare class EgFormAutocomplete {
|
|
6
|
+
private readonly formGroupDirective;
|
|
7
|
+
private readonly generatedId;
|
|
8
|
+
private readonly _config;
|
|
9
|
+
label: _angular_core.InputSignal<string | undefined>;
|
|
10
|
+
controlId: _angular_core.InputSignal<string | undefined>;
|
|
11
|
+
controlName: _angular_core.InputSignal<string>;
|
|
12
|
+
error: _angular_core.InputSignal<string | undefined>;
|
|
13
|
+
hint: _angular_core.InputSignal<string | undefined>;
|
|
14
|
+
id: _angular_core.InputSignal<string | undefined>;
|
|
15
|
+
placeholder: _angular_core.InputSignal<string>;
|
|
16
|
+
emptyText: _angular_core.InputSignal<string>;
|
|
17
|
+
disabled: _angular_core.InputSignal<boolean>;
|
|
18
|
+
required: _angular_core.InputSignal<boolean>;
|
|
19
|
+
options: _angular_core.InputSignal<string[]>;
|
|
20
|
+
readonly effectiveId: _angular_core.Signal<string>;
|
|
21
|
+
readonly errorId: _angular_core.Signal<string>;
|
|
22
|
+
readonly hintId: _angular_core.Signal<string>;
|
|
23
|
+
/**
|
|
24
|
+
* Combined lock for the brain `linkedSignal`-based disabled state: the raw
|
|
25
|
+
* input write always carries the resolved value, so a same-pass
|
|
26
|
+
* wrapper-toggle + `control.disable()` cannot clobber CVA state.
|
|
27
|
+
*/
|
|
28
|
+
effectiveDisabled(): boolean;
|
|
29
|
+
userClass: _angular_core.InputSignal<ClassValue>;
|
|
30
|
+
labelClass: _angular_core.InputSignal<string>;
|
|
31
|
+
controlClass: _angular_core.InputSignal<string>;
|
|
32
|
+
inputClass: _angular_core.InputSignal<string>;
|
|
33
|
+
errorClass: _angular_core.InputSignal<string>;
|
|
34
|
+
hintClass: _angular_core.InputSignal<string>;
|
|
35
|
+
$userClass: _angular_core.Signal<string>;
|
|
36
|
+
$labelClass: _angular_core.Signal<string>;
|
|
37
|
+
$controlClass: _angular_core.Signal<string>;
|
|
38
|
+
$inputClass: _angular_core.Signal<string>;
|
|
39
|
+
$errorClass: _angular_core.Signal<string>;
|
|
40
|
+
$hintClass: _angular_core.Signal<string>;
|
|
41
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<EgFormAutocomplete, never>;
|
|
42
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<EgFormAutocomplete, "eg-form-autocomplete", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "controlId": { "alias": "controlId"; "required": false; "isSignal": true; }; "controlName": { "alias": "controlName"; "required": false; "isSignal": true; }; "error": { "alias": "error"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "id": { "alias": "id"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "emptyText": { "alias": "emptyText"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; "options": { "alias": "options"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "labelClass": { "alias": "labelClass"; "required": false; "isSignal": true; }; "controlClass": { "alias": "controlClass"; "required": false; "isSignal": true; }; "inputClass": { "alias": "inputClass"; "required": false; "isSignal": true; }; "errorClass": { "alias": "errorClass"; "required": false; "isSignal": true; }; "hintClass": { "alias": "hintClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface EgFormAutocompleteConfig {
|
|
46
|
+
/**
|
|
47
|
+
* Global class defaults for `eg-form-autocomplete` styling slots.
|
|
48
|
+
* Each is merged under the matching per-instance `*Class` input
|
|
49
|
+
* (library base < global config < per-instance).
|
|
50
|
+
*/
|
|
51
|
+
labelClass?: string;
|
|
52
|
+
controlClass?: string;
|
|
53
|
+
inputClass?: string;
|
|
54
|
+
errorClass?: string;
|
|
55
|
+
hintClass?: string;
|
|
56
|
+
}
|
|
57
|
+
declare function provideEgFormAutocompleteConfig(config: Partial<EgFormAutocompleteConfig>): ValueProvider;
|
|
58
|
+
declare function injectEgFormAutocompleteConfig(): EgFormAutocompleteConfig;
|
|
59
|
+
|
|
60
|
+
export { EgFormAutocomplete, injectEgFormAutocompleteConfig, provideEgFormAutocompleteConfig };
|
|
61
|
+
export type { EgFormAutocompleteConfig };
|
package/form-checkbox/README.md
CHANGED
|
@@ -1,3 +1,323 @@
|
|
|
1
|
-
# Form Checkbox
|
|
1
|
+
# Form Checkbox (`@egose/shadcn-theme-ng/form-checkbox`)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A ready-made reactive-form checkbox row: `hlm-checkbox` + label + required marker with automatic `hlm-error` / `hlm-hint` display, wrapped in `eg-form-field` error switching. Equivalent to shadcn/ui `Form` + `Checkbox` composition.
|
|
4
|
+
|
|
5
|
+
The Angular implementation is a standalone `ControlValueAccessor`-compatible wrapper (not a brain
|
|
6
|
+
primitive itself): it renders `HlmCheckbox` bound with `formControlName`, `HlmLabel`, `EgFormField`
|
|
7
|
+
from `@egose/shadcn-theme-ng/form-field-simple`, and `HlmError` / `HlmHint` from
|
|
8
|
+
`@egose/shadcn-theme-ng/form-field`. It must live inside a `FormGroupDirective` (a
|
|
9
|
+
`[formGroup]` parent) and forwards `ControlContainer` to it. Ids are generated by
|
|
10
|
+
`HlmFormIdGenerator` unless overridden.
|
|
11
|
+
|
|
12
|
+
> **Ships as:** `@egose/shadcn-theme-ng/form-checkbox` and `@egose/shadcn-theme-ng-tw/form-checkbox`
|
|
13
|
+
> (the `tw:`-prefixed Tailwind variant). Both expose the identical TypeScript surface; only the
|
|
14
|
+
> emitted Tailwind class strings differ. See the [package README](../../README.md) for install
|
|
15
|
+
> steps, peer dependencies, and Tailwind setup. Do not publish this project directory independently.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Plain Tailwind (no prefix)
|
|
21
|
+
npm install @egose/shadcn-theme-ng
|
|
22
|
+
|
|
23
|
+
# tw:-prefixed Tailwind variant
|
|
24
|
+
npm install @egose/shadcn-theme-ng-tw
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Peer dependencies (Angular, `@spartan-ng/brain`, `@ng-icons/*`, `rxjs`, …) are documented in the
|
|
28
|
+
[package README](../../README.md#peer-dependencies). This subpath additionally relies at runtime on
|
|
29
|
+
`@egose/shadcn-theme-ng/checkbox`, `@egose/shadcn-theme-ng/label`,
|
|
30
|
+
`@egose/shadcn-theme-ng/form-field`, and `@egose/shadcn-theme-ng/form-field-simple`.
|
|
31
|
+
|
|
32
|
+
## Imports
|
|
33
|
+
|
|
34
|
+
Exported from the subpath root (`projects/form-checkbox/src/public-api.ts`). Note: this subpath
|
|
35
|
+
exports a single standalone component — there is no `*Imports` array or `*Module`:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { EgFormCheckbox } from '@egose/shadcn-theme-ng/form-checkbox';
|
|
39
|
+
// tw variant: replace with '@egose/shadcn-theme-ng-tw/form-checkbox'
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Standalone usage:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { Component } from '@angular/core';
|
|
46
|
+
import { ReactiveFormsModule } from '@angular/forms';
|
|
47
|
+
import { EgFormCheckbox } from '@egose/shadcn-theme-ng/form-checkbox';
|
|
48
|
+
|
|
49
|
+
@Component({
|
|
50
|
+
selector: 'app-demo',
|
|
51
|
+
standalone: true,
|
|
52
|
+
imports: [ReactiveFormsModule, EgFormCheckbox],
|
|
53
|
+
template: `...`,
|
|
54
|
+
})
|
|
55
|
+
export class DemoComponent {}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
NgModule-based consumer: add `EgFormCheckbox` (and `ReactiveFormsModule`) to the module's `imports`
|
|
59
|
+
— it is a standalone component, not a module.
|
|
60
|
+
|
|
61
|
+
`ControlValueAccessor` behavior: `eg-form-checkbox` itself is not a `ControlValueAccessor`; the
|
|
62
|
+
inner `hlm-checkbox` is bound via `[formControlName]="controlName()"`, so the parent `FormGroup`
|
|
63
|
+
owns the value. `checked()` sets the initial checkbox input; the form control is the source of
|
|
64
|
+
truth afterwards.
|
|
65
|
+
|
|
66
|
+
## Anatomy / Structure
|
|
67
|
+
|
|
68
|
+
```html
|
|
69
|
+
<form [formGroup]="form">
|
|
70
|
+
<eg-form-checkbox
|
|
71
|
+
controlName="acceptTerms"
|
|
72
|
+
label="Accept terms and conditions"
|
|
73
|
+
[required]="true"
|
|
74
|
+
hint="You must accept to continue."
|
|
75
|
+
error="You must accept the terms."
|
|
76
|
+
/>
|
|
77
|
+
</form>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Selector (from source): `eg-form-checkbox` (standalone component).
|
|
81
|
+
|
|
82
|
+
## API reference
|
|
83
|
+
|
|
84
|
+
### `EgFormCheckbox` — `eg-form-checkbox`
|
|
85
|
+
|
|
86
|
+
| Input | Type | Default | Description |
|
|
87
|
+
| --------------- | --------------------- | ------- | ------------------------------------------------------------------------------------------- |
|
|
88
|
+
| `controlName` | `string` | `''` | `formControlName` key inside the parent `FormGroup`. **Required.** |
|
|
89
|
+
| `label` | `string` | `''` | Label text next to the checkbox. |
|
|
90
|
+
| `error` | `string \| undefined` | — | Error text shown when the control is invalid + touched/dirty (via `EgFormField` switching). |
|
|
91
|
+
| `hint` | `string \| undefined` | — | Hint text shown when there is no error to display. |
|
|
92
|
+
| `controlId` | `string \| undefined` | — | Explicit control id (first priority for `effectiveId`). |
|
|
93
|
+
| `id` | `string \| undefined` | — | Fallback id (second priority). |
|
|
94
|
+
| `name` | `string \| undefined` | — | Checkbox `name` attribute (defaults to `controlName`). |
|
|
95
|
+
| `checked` | `boolean` | `false` | Initial checked state passed to `hlm-checkbox`. |
|
|
96
|
+
| `required` | `boolean` | `false` | Shows a red `*` and sets checkbox `required`. |
|
|
97
|
+
| `disabled` | `boolean` | `false` | Locks interaction via checkbox `wrapperDisabled` (does not write to the form control). |
|
|
98
|
+
| `class` | `ClassValue` | `''` | Extra host classes. |
|
|
99
|
+
| `checkboxClass` | `string` | `''` | Extra classes for `hlm-checkbox`. |
|
|
100
|
+
| `labelClass` | `string` | `''` | Extra classes for the label. |
|
|
101
|
+
| `errorClass` | `string` | `''` | Extra classes for `hlm-error`. |
|
|
102
|
+
| `hintClass` | `string` | `''` | Extra classes for `hlm-hint`. |
|
|
103
|
+
|
|
104
|
+
| Member | Description |
|
|
105
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
106
|
+
| `effectiveId` | `controlId() \|\| id() \|\| generated` — wired to checkbox `id` and label `for`. |
|
|
107
|
+
| `errorId` / `hintId` | `effectiveId + '-error' / '-hint'` for `aria-describedby`. |
|
|
108
|
+
| `describedBy()` | Returns `errorId` when `error()` is set and the control is invalid + dirty/touched, else `hintId` when `hint()` is set, else `null`. |
|
|
109
|
+
|
|
110
|
+
Requires a `[formGroup]` ancestor: the component injects `FormGroupDirective` and provides
|
|
111
|
+
`ControlContainer → FormGroupDirective` so `formControlName` resolves.
|
|
112
|
+
|
|
113
|
+
## Examples
|
|
114
|
+
|
|
115
|
+
### 1. Basic required terms checkbox
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
import { Component, inject } from '@angular/core';
|
|
119
|
+
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
120
|
+
import { EgFormCheckbox } from '@egose/shadcn-theme-ng/form-checkbox';
|
|
121
|
+
|
|
122
|
+
@Component({
|
|
123
|
+
selector: 'app-terms',
|
|
124
|
+
standalone: true,
|
|
125
|
+
imports: [ReactiveFormsModule, EgFormCheckbox],
|
|
126
|
+
template: `
|
|
127
|
+
<form [formGroup]="form" (ngSubmit)="submit()">
|
|
128
|
+
<eg-form-checkbox
|
|
129
|
+
controlName="accept"
|
|
130
|
+
label="Accept terms and conditions"
|
|
131
|
+
[required]="true"
|
|
132
|
+
error="You must accept the terms."
|
|
133
|
+
/>
|
|
134
|
+
<button type="submit" [disabled]="form.invalid">Continue</button>
|
|
135
|
+
</form>
|
|
136
|
+
`,
|
|
137
|
+
})
|
|
138
|
+
export class TermsComponent {
|
|
139
|
+
private readonly fb = inject(FormBuilder);
|
|
140
|
+
readonly form = this.fb.group({ accept: [false, Validators.requiredTrue] });
|
|
141
|
+
submit() {
|
|
142
|
+
console.log(this.form.value);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### 2. Hint + validation error display
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import { Component, inject } from '@angular/core';
|
|
151
|
+
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
152
|
+
import { EgFormCheckbox } from '@egose/shadcn-theme-ng/form-checkbox';
|
|
153
|
+
|
|
154
|
+
@Component({
|
|
155
|
+
selector: 'app-newsletter',
|
|
156
|
+
standalone: true,
|
|
157
|
+
imports: [ReactiveFormsModule, EgFormCheckbox],
|
|
158
|
+
template: `
|
|
159
|
+
<form [formGroup]="form">
|
|
160
|
+
<eg-form-checkbox
|
|
161
|
+
controlName="newsletter"
|
|
162
|
+
label="Email me news and offers"
|
|
163
|
+
hint="One email per month, unsubscribe anytime."
|
|
164
|
+
error="Please confirm your preference."
|
|
165
|
+
/>
|
|
166
|
+
</form>
|
|
167
|
+
<p class="tw:text-sm">Value: {{ form.value.newsletter }}</p>
|
|
168
|
+
`,
|
|
169
|
+
})
|
|
170
|
+
export class NewsletterComponent {
|
|
171
|
+
private readonly fb = inject(FormBuilder);
|
|
172
|
+
readonly form = this.fb.group({ newsletter: [true, Validators.requiredTrue] });
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 3. Disabled / locked checkbox
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
import { Component, inject } from '@angular/core';
|
|
180
|
+
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
|
181
|
+
import { EgFormCheckbox } from '@egose/shadcn-theme-ng/form-checkbox';
|
|
182
|
+
|
|
183
|
+
@Component({
|
|
184
|
+
selector: 'app-locked',
|
|
185
|
+
standalone: true,
|
|
186
|
+
imports: [ReactiveFormsModule, EgFormCheckbox],
|
|
187
|
+
template: `
|
|
188
|
+
<form [formGroup]="form">
|
|
189
|
+
<eg-form-checkbox
|
|
190
|
+
controlName="readonly"
|
|
191
|
+
label="Two-factor authentication (enforced)"
|
|
192
|
+
[checked]="true"
|
|
193
|
+
[disabled]="true"
|
|
194
|
+
hint="Managed by your organization."
|
|
195
|
+
/>
|
|
196
|
+
</form>
|
|
197
|
+
`,
|
|
198
|
+
})
|
|
199
|
+
export class LockedComponent {
|
|
200
|
+
private readonly fb = inject(FormBuilder);
|
|
201
|
+
readonly form = this.fb.group({ readonly: [true] });
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
> `disabled` locks the UI via `wrapperDisabled` without disabling the form control itself, so the
|
|
206
|
+
> value still submits. To exclude the value, call `form.get('readonly')?.disable()` instead.
|
|
207
|
+
|
|
208
|
+
### 4. Custom ids + styling hooks
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
import { Component, inject } from '@angular/core';
|
|
212
|
+
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
|
213
|
+
import { EgFormCheckbox } from '@egose/shadcn-theme-ng/form-checkbox';
|
|
214
|
+
|
|
215
|
+
@Component({
|
|
216
|
+
selector: 'app-styled-check',
|
|
217
|
+
standalone: true,
|
|
218
|
+
imports: [ReactiveFormsModule, EgFormCheckbox],
|
|
219
|
+
template: `
|
|
220
|
+
<form [formGroup]="form">
|
|
221
|
+
<eg-form-checkbox
|
|
222
|
+
controlName="marketing"
|
|
223
|
+
controlId="marketing-opt-in"
|
|
224
|
+
label="Send me product updates"
|
|
225
|
+
checkboxClass="tw:border-primary"
|
|
226
|
+
labelClass="tw:font-medium"
|
|
227
|
+
class="tw:rounded-md tw:border tw:p-3"
|
|
228
|
+
/>
|
|
229
|
+
</form>
|
|
230
|
+
`,
|
|
231
|
+
})
|
|
232
|
+
export class StyledCheckComponent {
|
|
233
|
+
private readonly fb = inject(FormBuilder);
|
|
234
|
+
readonly form = this.fb.group({ marketing: [false] });
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### 5. Settings list (multiple checkboxes, one group)
|
|
239
|
+
|
|
240
|
+
```ts
|
|
241
|
+
import { Component, inject } from '@angular/core';
|
|
242
|
+
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
|
243
|
+
import { EgFormCheckbox } from '@egose/shadcn-theme-ng/form-checkbox';
|
|
244
|
+
|
|
245
|
+
@Component({
|
|
246
|
+
selector: 'app-settings',
|
|
247
|
+
standalone: true,
|
|
248
|
+
imports: [ReactiveFormsModule, EgFormCheckbox],
|
|
249
|
+
template: `
|
|
250
|
+
<form [formGroup]="form" class="tw:grid tw:gap-3">
|
|
251
|
+
<eg-form-checkbox controlName="email" label="Email notifications" />
|
|
252
|
+
<eg-form-checkbox controlName="sms" label="SMS notifications" hint="Carrier rates may apply." />
|
|
253
|
+
<eg-form-checkbox controlName="push" label="Push notifications" />
|
|
254
|
+
</form>
|
|
255
|
+
<pre class="tw:text-xs">{{ form.value | json }}</pre>
|
|
256
|
+
`,
|
|
257
|
+
})
|
|
258
|
+
export class SettingsComponent {
|
|
259
|
+
private readonly fb = inject(FormBuilder);
|
|
260
|
+
readonly form = this.fb.group({ email: [true], sms: [false], push: [true] });
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### 6. Submitted-state validation (mark all touched)
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
import { Component, inject } from '@angular/core';
|
|
268
|
+
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
269
|
+
import { EgFormCheckbox } from '@egose/shadcn-theme-ng/form-checkbox';
|
|
270
|
+
|
|
271
|
+
@Component({
|
|
272
|
+
selector: 'app-submit-check',
|
|
273
|
+
standalone: true,
|
|
274
|
+
imports: [ReactiveFormsModule, EgFormCheckbox],
|
|
275
|
+
template: `
|
|
276
|
+
<form [formGroup]="form" (ngSubmit)="submit()">
|
|
277
|
+
<eg-form-checkbox
|
|
278
|
+
controlName="consent"
|
|
279
|
+
label="I consent to data processing"
|
|
280
|
+
[required]="true"
|
|
281
|
+
error="Consent is required to create your account."
|
|
282
|
+
/>
|
|
283
|
+
<button type="submit">Create account</button>
|
|
284
|
+
</form>
|
|
285
|
+
`,
|
|
286
|
+
})
|
|
287
|
+
export class SubmitCheckComponent {
|
|
288
|
+
private readonly fb = inject(FormBuilder);
|
|
289
|
+
readonly form = this.fb.group({ consent: [false, Validators.requiredTrue] });
|
|
290
|
+
submit() {
|
|
291
|
+
this.form.markAllAsTouched();
|
|
292
|
+
if (this.form.valid) console.log('creating account…');
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## Accessibility notes
|
|
298
|
+
|
|
299
|
+
- The checkbox `id` and label `for` are generated (`eg-form-checkbox-<app>-<n>`) unless `controlId`/`id` is given — labels are always programmatically associated.
|
|
300
|
+
- `aria-describedby` points at the error id only while the control is invalid + touched/dirty, otherwise at the hint id — screen readers hear the right message in each state.
|
|
301
|
+
- The required marker (`*`) is visual; the underlying `hlm-checkbox` also receives `required` so assistive tech announces it.
|
|
302
|
+
- Keep the component inside a `<form>` with a submit path; the row itself is a single tab stop (the checkbox).
|
|
303
|
+
|
|
304
|
+
## Theming / CSS variables
|
|
305
|
+
|
|
306
|
+
No component-specific CSS variables. Style per-instance via `class`, `checkboxClass`, `labelClass`, `errorClass`, `hintClass` inputs. The row layout (`flex items-center gap-1`) is fixed in the template.
|
|
307
|
+
|
|
308
|
+
Global defaults per styling slot via the wrapper config (precedence: library base < global config < per-instance):
|
|
309
|
+
|
|
310
|
+
```ts
|
|
311
|
+
import { provideEgFormCheckboxConfig } from '@egose/shadcn-theme-ng/form-checkbox';
|
|
312
|
+
|
|
313
|
+
await bootstrapApplication(App, {
|
|
314
|
+
providers: [provideEgFormCheckboxConfig({ checkboxClass: 'tw:size-5', labelClass: 'tw:font-medium' })],
|
|
315
|
+
});
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Related subpaths
|
|
319
|
+
|
|
320
|
+
- `@egose/shadcn-theme-ng/checkbox` — standalone `hlm-checkbox` when you need a custom layout.
|
|
321
|
+
- `@egose/shadcn-theme-ng/form-field-simple` — `eg-form-field` error/hint switching used internally.
|
|
322
|
+
- `@egose/shadcn-theme-ng/form-field` — `hlm-form-field` / `hlm-error` / `hlm-hint` primitives.
|
|
323
|
+
- `@egose/shadcn-theme-ng/label` — `HlmLabel` used for the row label.
|