@egose/shadcn-theme-ng 0.5.2 → 0.6.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 +12 -11
- package/data-table/README.md +164 -0
- package/data-table/fesm2022/data-table.mjs +677 -0
- package/data-table/package.json +25 -0
- package/data-table/types/data-table.d.ts +483 -0
- package/dropdown-menu/README.md +2 -0
- package/form-checkbox/README.md +22 -22
- package/form-text-input/fesm2022/form-text-input.mjs +1 -1
- package/form-textarea/fesm2022/form-textarea.mjs +1 -1
- package/input/README.md +7 -12
- package/input/fesm2022/input.mjs +7 -4
- package/input/types/input.d.ts +3 -1
- package/layout-simple/fesm2022/layout-simple.mjs +1 -1
- package/package.json +6 -1
- package/phone-input/fesm2022/phone-input.mjs +1 -1
- package/stepper/README.md +75 -52
- package/stepper/fesm2022/stepper.mjs +30 -6
- package/stepper/types/stepper.d.ts +22 -14
- package/table/README.md +2 -0
- package/table/fesm2022/table.mjs +12 -8
- package/table/types/table.d.ts +7 -2
|
@@ -127,7 +127,7 @@ class EgFormTextInput {
|
|
|
127
127
|
$hintClass = computed(() => hlm("mt-0", this._shared.hintClass, this._config.hintClass, this.hintClass()), /* @ts-ignore */
|
|
128
128
|
...(ngDevMode ? [{ debugName: "$hintClass" }] : /* istanbul ignore next */ []));
|
|
129
129
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormTextInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
130
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormTextInput, isStandalone: true, selector: "eg-form-text-input", 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 }, autoError: { classPropertyName: "autoError", publicName: "autoError", 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 }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, minlength: { classPropertyName: "minlength", publicName: "minlength", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", 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 }, 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 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 <input\n hlmInput\n [attr.aria-label]=\"lbl\"\n [id]=\"effectiveId()\"\n [name]=\"cnm || name()\"\n [formControlName]=\"cnm\"\n [class]=\"$inputClass()\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [attr.disabled]=\"effectiveDisabled() ? '' : null\"\n [ariaDescribedby]=\"describedBy()\"\n [max]=\"max()\"\n [min]=\"min()\"\n [maxlength]=\"maxlength()\"\n [minlength]=\"minlength()\"\n [pattern]=\"pattern()\"\n [autocomplete]=\"autocomplete()\"\n [autofocus]=\"autofocus()\"\n [required]=\"rqrd\"\n />\n\n @if (showError()) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ resolvedError() }}\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.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { 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: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby"] }] });
|
|
130
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormTextInput, isStandalone: true, selector: "eg-form-text-input", 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 }, autoError: { classPropertyName: "autoError", publicName: "autoError", 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 }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, minlength: { classPropertyName: "minlength", publicName: "minlength", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, pattern: { classPropertyName: "pattern", publicName: "pattern", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", 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 }, 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 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 <input\n hlmInput\n [attr.aria-label]=\"lbl\"\n [id]=\"effectiveId()\"\n [name]=\"cnm || name()\"\n [formControlName]=\"cnm\"\n [class]=\"$inputClass()\"\n [type]=\"type()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [attr.disabled]=\"effectiveDisabled() ? '' : null\"\n [ariaDescribedby]=\"describedBy()\"\n [max]=\"max()\"\n [min]=\"min()\"\n [maxlength]=\"maxlength()\"\n [minlength]=\"minlength()\"\n [pattern]=\"pattern()\"\n [autocomplete]=\"autocomplete()\"\n [autofocus]=\"autofocus()\"\n [required]=\"rqrd\"\n />\n\n @if (showError()) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ resolvedError() }}\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.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { 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: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby", "size"] }] });
|
|
131
131
|
}
|
|
132
132
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormTextInput, decorators: [{
|
|
133
133
|
type: Component,
|
|
@@ -120,7 +120,7 @@ class EgFormTextarea {
|
|
|
120
120
|
$hintClass = computed(() => hlm("mt-0", this._shared.hintClass, this._config.hintClass, this.hintClass()), /* @ts-ignore */
|
|
121
121
|
...(ngDevMode ? [{ debugName: "$hintClass" }] : /* istanbul ignore next */ []));
|
|
122
122
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
123
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormTextarea, isStandalone: true, selector: "eg-form-textarea", 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 }, autoError: { classPropertyName: "autoError", publicName: "autoError", 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 }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, minlength: { classPropertyName: "minlength", publicName: "minlength", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, cols: { classPropertyName: "cols", publicName: "cols", 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 }, textareaClass: { classPropertyName: "textareaClass", publicName: "textareaClass", 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 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 <textarea\n hlmInput\n [attr.aria-label]=\"lbl\"\n [id]=\"effectiveId()\"\n [name]=\"cnm || name()\"\n [formControlName]=\"cnm\"\n [class]=\"$textareaClass()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [attr.disabled]=\"effectiveDisabled() ? '' : null\"\n [ariaDescribedby]=\"describedBy()\"\n [maxlength]=\"maxlength()\"\n [minlength]=\"minlength()\"\n [required]=\"rqrd\"\n [rows]=\"rows()\"\n [cols]=\"cols()\"\n ></textarea>\n\n @if (showError()) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ resolvedError() }}\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.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { 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: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby"] }] });
|
|
123
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgFormTextarea, isStandalone: true, selector: "eg-form-textarea", 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 }, autoError: { classPropertyName: "autoError", publicName: "autoError", 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 }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, maxlength: { classPropertyName: "maxlength", publicName: "maxlength", isSignal: true, isRequired: false, transformFunction: null }, minlength: { classPropertyName: "minlength", publicName: "minlength", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, cols: { classPropertyName: "cols", publicName: "cols", 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 }, textareaClass: { classPropertyName: "textareaClass", publicName: "textareaClass", 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 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 <textarea\n hlmInput\n [attr.aria-label]=\"lbl\"\n [id]=\"effectiveId()\"\n [name]=\"cnm || name()\"\n [formControlName]=\"cnm\"\n [class]=\"$textareaClass()\"\n [placeholder]=\"placeholder()\"\n [readonly]=\"readonly()\"\n [attr.disabled]=\"effectiveDisabled() ? '' : null\"\n [ariaDescribedby]=\"describedBy()\"\n [maxlength]=\"maxlength()\"\n [minlength]=\"minlength()\"\n [required]=\"rqrd\"\n [rows]=\"rows()\"\n [cols]=\"cols()\"\n ></textarea>\n\n @if (showError()) {\n <hlm-error [id]=\"errorId()\" [class]=\"$errorClass()\">\n {{ resolvedError() }}\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.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { 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: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby", "size"] }] });
|
|
124
124
|
}
|
|
125
125
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgFormTextarea, decorators: [{
|
|
126
126
|
type: Component,
|
package/input/README.md
CHANGED
|
@@ -58,11 +58,12 @@ The directive matches `input[hlmInput]` usage in practice (selector `[hlmInput]`
|
|
|
58
58
|
|
|
59
59
|
### `[hlmInput]` — `HlmInput`
|
|
60
60
|
|
|
61
|
-
| Input | Type
|
|
62
|
-
| ----------------- |
|
|
63
|
-
| `ariaDescribedby` | `string \| null`
|
|
64
|
-
| `id` | (via `BrnInput`)
|
|
65
|
-
| `forceInvalid` | (via `BrnInput`)
|
|
61
|
+
| Input | Type | Default | Description |
|
|
62
|
+
| ----------------- | --------------------- | --------- | ------------------------------------------------------------------------------------------------------------------- |
|
|
63
|
+
| `ariaDescribedby` | `string \| null` | `null` | Bound to `aria-describedby`. Combine with `<hlm-error>`/`<hlm-hint>` ids (the form wrappers do this automatically). |
|
|
64
|
+
| `id` | (via `BrnInput`) | — | Forwarded to the `BrnInput` host directive. |
|
|
65
|
+
| `forceInvalid` | (via `BrnInput`) | — | Forwarded to the `BrnInput` host directive; forces the `data-matches-spartan-invalid` error styles. |
|
|
66
|
+
| `size` | `sm \| default \| lg` | `default` | Height density: `h-8` / `h-9` / `h-10`. |
|
|
66
67
|
|
|
67
68
|
No outputs. Visual states are attribute-driven: `data-matches-spartan-invalid=true` switches the border/ring to destructive; `disabled` applies `pointer-events-none`, `cursor-not-allowed`, `opacity-50`. Base geometry: `h-9`, `rounded-md`, `text-base` (`md:text-sm`), full width.
|
|
68
69
|
|
|
@@ -180,13 +181,7 @@ import { HlmError, HlmHint } from '@egose/shadcn-theme-ng/form-field';
|
|
|
180
181
|
template: `
|
|
181
182
|
<form [formGroup]="form">
|
|
182
183
|
<label for="handle">Handle</label>
|
|
183
|
-
<input
|
|
184
|
-
hlmInput
|
|
185
|
-
id="handle"
|
|
186
|
-
formControlName="handle"
|
|
187
|
-
placeholder="@jane"
|
|
188
|
-
[ariaDescribedby]="describedBy()"
|
|
189
|
-
/>
|
|
184
|
+
<input hlmInput id="handle" formControlName="handle" placeholder="@jane" [ariaDescribedby]="describedBy()" />
|
|
190
185
|
@if (showError()) {
|
|
191
186
|
<hlm-error id="handle-error">Use 3+ lowercase letters.</hlm-error>
|
|
192
187
|
} @else {
|
package/input/fesm2022/input.mjs
CHANGED
|
@@ -4,16 +4,19 @@ import * as i2 from '@spartan-ng/brain/field';
|
|
|
4
4
|
import { BrnFieldControlDescribedBy } from '@spartan-ng/brain/field';
|
|
5
5
|
import * as i1 from '@spartan-ng/brain/input';
|
|
6
6
|
import { BrnInput } from '@spartan-ng/brain/input';
|
|
7
|
-
import { classes } from '@egose/shadcn-theme-ng/utils';
|
|
7
|
+
import { classes, hlm } from '@egose/shadcn-theme-ng/utils';
|
|
8
8
|
|
|
9
9
|
class HlmInput {
|
|
10
10
|
ariaDescribedby = input(null, /* @ts-ignore */
|
|
11
11
|
...(ngDevMode ? [{ debugName: "ariaDescribedby" }] : /* istanbul ignore next */ []));
|
|
12
|
+
/** Height density. Merged after the base height class, so it wins via `twMerge`. */
|
|
13
|
+
size = input('default', /* @ts-ignore */
|
|
14
|
+
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
12
15
|
constructor() {
|
|
13
|
-
classes(() => "dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 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 h-9 rounded-md border bg-transparent px-2.5 py-1 text-base shadow-xs transition-[color,box-shadow] file:h-7 file:text-sm file:font-medium focus-visible:ring-3 data-[matches-spartan-invalid=true]:ring-3 md:text-sm file:text-foreground placeholder:text-muted-foreground w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50");
|
|
16
|
+
classes(() => hlm("dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 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 h-9 rounded-md border bg-transparent px-2.5 py-1 text-base shadow-xs transition-[color,box-shadow] file:h-7 file:text-sm file:font-medium focus-visible:ring-3 data-[matches-spartan-invalid=true]:ring-3 md:text-sm file:text-foreground placeholder:text-muted-foreground w-full min-w-0 outline-none file:inline-flex file:border-0 file:bg-transparent disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50", this.size() === 'sm' ? "h-8" : this.size() === 'lg' ? "h-10" : ''));
|
|
14
17
|
}
|
|
15
18
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmInput, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
16
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.3", type: HlmInput, isStandalone: true, selector: "[hlmInput]", inputs: { ariaDescribedby: { classPropertyName: "ariaDescribedby", publicName: "ariaDescribedby", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "input" }, properties: { "attr.aria-describedby": "ariaDescribedby()" } }, hostDirectives: [{ directive: i1.BrnInput, inputs: ["id", "id", "forceInvalid", "forceInvalid"] }, { directive: i2.BrnFieldControlDescribedBy }], ngImport: i0 });
|
|
19
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.3", type: HlmInput, isStandalone: true, selector: "[hlmInput]", inputs: { ariaDescribedby: { classPropertyName: "ariaDescribedby", publicName: "ariaDescribedby", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "input" }, properties: { "attr.aria-describedby": "ariaDescribedby()" } }, hostDirectives: [{ directive: i1.BrnInput, inputs: ["id", "id", "forceInvalid", "forceInvalid"] }, { directive: i2.BrnFieldControlDescribedBy }], ngImport: i0 });
|
|
17
20
|
}
|
|
18
21
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmInput, decorators: [{
|
|
19
22
|
type: Directive,
|
|
@@ -25,7 +28,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
25
28
|
'[attr.aria-describedby]': 'ariaDescribedby()',
|
|
26
29
|
},
|
|
27
30
|
}]
|
|
28
|
-
}], ctorParameters: () => [], propDecorators: { ariaDescribedby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedby", required: false }] }] } });
|
|
31
|
+
}], ctorParameters: () => [], propDecorators: { ariaDescribedby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedby", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
29
32
|
|
|
30
33
|
/*
|
|
31
34
|
* Public API Surface of input
|
package/input/types/input.d.ts
CHANGED
|
@@ -4,9 +4,11 @@ import * as i2 from '@spartan-ng/brain/field';
|
|
|
4
4
|
|
|
5
5
|
declare class HlmInput {
|
|
6
6
|
readonly ariaDescribedby: i0.InputSignal<string | null>;
|
|
7
|
+
/** Height density. Merged after the base height class, so it wins via `twMerge`. */
|
|
8
|
+
readonly size: i0.InputSignal<"sm" | "default" | "lg">;
|
|
7
9
|
constructor();
|
|
8
10
|
static ɵfac: i0.ɵɵFactoryDeclaration<HlmInput, never>;
|
|
9
|
-
static ɵdir: i0.ɵɵDirectiveDeclaration<HlmInput, "[hlmInput]", never, { "ariaDescribedby": { "alias": "ariaDescribedby"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.BrnInput; inputs: { "id": "id"; "forceInvalid": "forceInvalid"; }; outputs: {}; }, { directive: typeof i2.BrnFieldControlDescribedBy; inputs: {}; outputs: {}; }]>;
|
|
11
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<HlmInput, "[hlmInput]", never, { "ariaDescribedby": { "alias": "ariaDescribedby"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.BrnInput; inputs: { "id": "id"; "forceInvalid": "forceInvalid"; }; outputs: {}; }, { directive: typeof i2.BrnFieldControlDescribedBy; inputs: {}; outputs: {}; }]>;
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
declare const HlmInputImports: readonly [typeof HlmInput];
|
|
@@ -169,7 +169,7 @@ class EgLayoutSearch {
|
|
|
169
169
|
buttons[Math.min(index, buttons.length - 1)]?.nativeElement.focus();
|
|
170
170
|
}
|
|
171
171
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSearch, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
172
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgLayoutSearch, isStandalone: true, selector: "eg-layout-search", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, loadingText: { classPropertyName: "loadingText", publicName: "loadingText", isSignal: true, isRequired: false, transformFunction: null }, retryText: { classPropertyName: "retryText", publicName: "retryText", isSignal: true, isRequired: false, transformFunction: null }, loader: { classPropertyName: "loader", publicName: "loader", isSignal: true, isRequired: false, transformFunction: null }, resultLabel: { classPropertyName: "resultLabel", publicName: "resultLabel", isSignal: true, isRequired: false, transformFunction: null }, resultTemplate: { classPropertyName: "resultTemplate", publicName: "resultTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { resultSelected: "resultSelected" }, host: { classAttribute: "block min-w-0" }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }, { propertyName: "resultButtons", predicate: ["resultButton"], descendants: true, isSignal: true }], ngImport: i0, template: "\n <hlm-popover\n [state]=\"isOpen() ? 'open' : 'closed'\"\n (stateChanged)=\"setOpen($event === 'open')\"\n (closed)=\"setOpen(false)\"\n >\n <button\n hlmPopoverTrigger\n type=\"button\"\n class=\"flex min-h-11 w-full items-center gap-2 rounded-lg border border-border bg-foreground/3 px-3 text-left text-sm text-foreground/75 cursor-pointer hover:bg-foreground/5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring md:w-56\"\n >\n <ng-icon [svg]=\"searchIcon\" size=\"16px\" aria-hidden=\"true\" class=\"shrink-0\" />\n <span class=\"truncate\">{{ placeholder() }}</span>\n </button>\n <hlm-popover-content *hlmPopoverPortal class=\"w-80 max-w-[calc(100vw-2rem)] p-2\">\n <input\n #searchInput\n hlmInput\n type=\"search\"\n autocomplete=\"off\"\n [value]=\"query()\"\n (input)=\"query.set($any($event.target).value)\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"placeholder()\"\n (keydown.arrowdown)=\"focusResult(0, $event)\"\n class=\"mb-2 min-h-11\"\n />\n <div [attr.aria-busy]=\"isLoading()\" class=\"max-h-72 overflow-y-auto overscroll-contain\">\n @if (isLoading()) {\n <p role=\"status\" class=\"px-3 py-6 text-center text-sm text-foreground/75\">\n {{ loadingText() }}\n </p>\n } @else if (hasError()) {\n <div role=\"status\" class=\"space-y-3 px-3 py-4 text-sm\">\n <p>{{ errorText() }}</p>\n <button\n type=\"button\"\n (click)=\"retry()\"\n class=\"min-h-11 rounded-md border border-border px-3 font-medium cursor-pointer focus-visible:outline-2 focus-visible:outline-ring\"\n >\n {{ retryText() }}\n </button>\n </div>\n } @else if (!results().length) {\n <p role=\"status\" class=\"px-3 py-6 text-center text-sm text-foreground/75\">\n {{ emptyText() }}\n </p>\n } @else {\n @for (result of results(); track $index; let index = $index) {\n <button\n #resultButton\n type=\"button\"\n (click)=\"selectResult(result)\"\n (keydown.arrowdown)=\"focusResult(index + 1, $event)\"\n (keydown.arrowup)=\"focusResult(index - 1, $event)\"\n (keydown.home)=\"focusResult(0, $event)\"\n (keydown.end)=\"focusResult(results().length - 1, $event)\"\n class=\"flex min-h-11 w-full items-center rounded-md px-3 py-2 text-left text-sm cursor-pointer hover:bg-foreground/5 focus-visible:bg-foreground/10 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring\"\n >\n @if (resultTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"{ $implicit: result }\" />\n } @else {\n {{ labelFor(result) }}\n }\n </button>\n }\n }\n </div>\n </hlm-popover-content>\n </hlm-popover>\n ", isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: HlmPopover, selector: "[hlmPopover],hlm-popover" }, { kind: "directive", type: HlmPopoverTrigger, selector: "button[hlmPopoverTrigger],button[hlmPopoverTriggerFor]" }, { kind: "directive", type: HlmPopoverContent, selector: "[hlmPopoverContent],hlm-popover-content" }, { kind: "directive", type: HlmPopoverPortal, selector: "[hlmPopoverPortal]" }, { kind: "directive", type: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
172
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: EgLayoutSearch, isStandalone: true, selector: "eg-layout-search", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, emptyText: { classPropertyName: "emptyText", publicName: "emptyText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, loadingText: { classPropertyName: "loadingText", publicName: "loadingText", isSignal: true, isRequired: false, transformFunction: null }, retryText: { classPropertyName: "retryText", publicName: "retryText", isSignal: true, isRequired: false, transformFunction: null }, loader: { classPropertyName: "loader", publicName: "loader", isSignal: true, isRequired: false, transformFunction: null }, resultLabel: { classPropertyName: "resultLabel", publicName: "resultLabel", isSignal: true, isRequired: false, transformFunction: null }, resultTemplate: { classPropertyName: "resultTemplate", publicName: "resultTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { resultSelected: "resultSelected" }, host: { classAttribute: "block min-w-0" }, viewQueries: [{ propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true, isSignal: true }, { propertyName: "resultButtons", predicate: ["resultButton"], descendants: true, isSignal: true }], ngImport: i0, template: "\n <hlm-popover\n [state]=\"isOpen() ? 'open' : 'closed'\"\n (stateChanged)=\"setOpen($event === 'open')\"\n (closed)=\"setOpen(false)\"\n >\n <button\n hlmPopoverTrigger\n type=\"button\"\n class=\"flex min-h-11 w-full items-center gap-2 rounded-lg border border-border bg-foreground/3 px-3 text-left text-sm text-foreground/75 cursor-pointer hover:bg-foreground/5 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring md:w-56\"\n >\n <ng-icon [svg]=\"searchIcon\" size=\"16px\" aria-hidden=\"true\" class=\"shrink-0\" />\n <span class=\"truncate\">{{ placeholder() }}</span>\n </button>\n <hlm-popover-content *hlmPopoverPortal class=\"w-80 max-w-[calc(100vw-2rem)] p-2\">\n <input\n #searchInput\n hlmInput\n type=\"search\"\n autocomplete=\"off\"\n [value]=\"query()\"\n (input)=\"query.set($any($event.target).value)\"\n [placeholder]=\"placeholder()\"\n [attr.aria-label]=\"placeholder()\"\n (keydown.arrowdown)=\"focusResult(0, $event)\"\n class=\"mb-2 min-h-11\"\n />\n <div [attr.aria-busy]=\"isLoading()\" class=\"max-h-72 overflow-y-auto overscroll-contain\">\n @if (isLoading()) {\n <p role=\"status\" class=\"px-3 py-6 text-center text-sm text-foreground/75\">\n {{ loadingText() }}\n </p>\n } @else if (hasError()) {\n <div role=\"status\" class=\"space-y-3 px-3 py-4 text-sm\">\n <p>{{ errorText() }}</p>\n <button\n type=\"button\"\n (click)=\"retry()\"\n class=\"min-h-11 rounded-md border border-border px-3 font-medium cursor-pointer focus-visible:outline-2 focus-visible:outline-ring\"\n >\n {{ retryText() }}\n </button>\n </div>\n } @else if (!results().length) {\n <p role=\"status\" class=\"px-3 py-6 text-center text-sm text-foreground/75\">\n {{ emptyText() }}\n </p>\n } @else {\n @for (result of results(); track $index; let index = $index) {\n <button\n #resultButton\n type=\"button\"\n (click)=\"selectResult(result)\"\n (keydown.arrowdown)=\"focusResult(index + 1, $event)\"\n (keydown.arrowup)=\"focusResult(index - 1, $event)\"\n (keydown.home)=\"focusResult(0, $event)\"\n (keydown.end)=\"focusResult(results().length - 1, $event)\"\n class=\"flex min-h-11 w-full items-center rounded-md px-3 py-2 text-left text-sm cursor-pointer hover:bg-foreground/5 focus-visible:bg-foreground/10 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring\"\n >\n @if (resultTemplate(); as template) {\n <ng-container [ngTemplateOutlet]=\"template\" [ngTemplateOutletContext]=\"{ $implicit: result }\" />\n } @else {\n {{ labelFor(result) }}\n }\n </button>\n }\n }\n </div>\n </hlm-popover-content>\n </hlm-popover>\n ", isInline: true, dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: HlmPopover, selector: "[hlmPopover],hlm-popover" }, { kind: "directive", type: HlmPopoverTrigger, selector: "button[hlmPopoverTrigger],button[hlmPopoverTriggerFor]" }, { kind: "directive", type: HlmPopoverContent, selector: "[hlmPopoverContent],hlm-popover-content" }, { kind: "directive", type: HlmPopoverPortal, selector: "[hlmPopoverPortal]" }, { kind: "directive", type: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby", "size"] }, { kind: "component", type: NgIcon, selector: "ng-icon", inputs: ["name", "svg", "size", "strokeWidth", "color"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
173
173
|
}
|
|
174
174
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: EgLayoutSearch, decorators: [{
|
|
175
175
|
type: Component,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@egose/shadcn-theme-ng",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Angular shadcn UI theme",
|
|
5
5
|
"author": "Junmin Ahn",
|
|
6
6
|
"bundles": [
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"@angular/router": ">=22.0.0 <23.0.0",
|
|
32
32
|
"@ng-icons/core": ">=35.0.1 <36.0.0",
|
|
33
33
|
"@spartan-ng/brain": ">=1.3.2 <2.0.0",
|
|
34
|
+
"@tanstack/angular-table": ">=9.1.2 <10.0.0",
|
|
34
35
|
"rxjs": ">=7.8.0 <8.0.0"
|
|
35
36
|
},
|
|
36
37
|
"files": [
|
|
@@ -126,6 +127,10 @@
|
|
|
126
127
|
"types": "./context-menu/types/context-menu.d.ts",
|
|
127
128
|
"default": "./context-menu/fesm2022/context-menu.mjs"
|
|
128
129
|
},
|
|
130
|
+
"./data-table": {
|
|
131
|
+
"types": "./data-table/types/data-table.d.ts",
|
|
132
|
+
"default": "./data-table/fesm2022/data-table.mjs"
|
|
133
|
+
},
|
|
129
134
|
"./date-picker": {
|
|
130
135
|
"types": "./date-picker/types/date-picker.d.ts",
|
|
131
136
|
"default": "./date-picker/fesm2022/date-picker.mjs"
|
|
@@ -143,7 +143,7 @@ class HlmPhoneInput {
|
|
|
143
143
|
(input)="_handleInput($event)"
|
|
144
144
|
(blur)="_handleBlur()"
|
|
145
145
|
/>
|
|
146
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
146
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby", "size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
147
147
|
}
|
|
148
148
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmPhoneInput, decorators: [{
|
|
149
149
|
type: Component,
|
package/stepper/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Stepper (`@egose/shadcn-theme-ng/stepper`)
|
|
2
2
|
|
|
3
|
-
Multi-step workflow navigation, ported from the spartan stepper blocks. This subpath ships seven pieces — `HlmStepper` (root), `HlmStep` (step), `HlmStepHeader` (clickable header with indicator), `HlmStepLabel` (rich label template), `HlmStepContent` (lazy body), `HlmStepperNext` / `HlmStepperPrevious` (navigation buttons) — plus `provideHlmStepperConfig` / `injectHlmStepperConfig` for global defaults. All are thin shadcn-styled components over Angular CDK's `@angular/cdk/stepper` primitives (`CdkStepper`, `CdkStep`, `CdkStepHeader`, `CdkStepLabel`).
|
|
3
|
+
Multi-step workflow navigation, ported from the spartan stepper blocks. This subpath ships seven pieces — `HlmStepper` (root), `HlmStep` (step), `HlmStepHeader` (clickable header with indicator), `HlmStepLabel` (rich label template), `HlmStepContent` (lazy body), `HlmStepperNext` / `HlmStepperPrevious` (navigation buttons) — plus `provideHlmStepperConfig` / `injectHlmStepperConfig` for global defaults. Headers automatically show the full label in a styled tooltip on hover/focus (overridable per step via `tooltip`). All are thin shadcn-styled components over Angular CDK's `@angular/cdk/stepper` primitives (`CdkStepper`, `CdkStep`, `CdkStepHeader`, `CdkStepLabel`).
|
|
4
4
|
|
|
5
5
|
> **Ships as:** `@egose/shadcn-theme-ng/stepper` and `@egose/shadcn-theme-ng-tw/stepper` (the `tw:`-prefixed Tailwind variant). See the [package README](../../README.md) for install steps, peer dependencies, Tailwind setup, and testing/release guidance. Do not publish this project directory independently.
|
|
6
6
|
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
HlmStepperPrevious,
|
|
34
34
|
injectHlmStepperConfig,
|
|
35
35
|
provideHlmStepperConfig,
|
|
36
|
+
type HlmStepTooltipPosition,
|
|
36
37
|
} from '@egose/shadcn-theme-ng/stepper';
|
|
37
38
|
// tw variant: swap to '@egose/shadcn-theme-ng-tw/stepper'
|
|
38
39
|
```
|
|
@@ -62,19 +63,19 @@ import { HlmStepperModule } from '@egose/shadcn-theme-ng/stepper';
|
|
|
62
63
|
export class FeatureModule {}
|
|
63
64
|
```
|
|
64
65
|
|
|
65
|
-
| Symbol
|
|
66
|
-
|
|
|
67
|
-
| `HlmStepper`
|
|
68
|
-
| `HlmStep`
|
|
69
|
-
| `HlmStepHeader`
|
|
70
|
-
| `HlmStepLabel`
|
|
71
|
-
| `HlmStepContent`
|
|
72
|
-
| `HlmStepperNext`
|
|
73
|
-
| `HlmStepperPrevious`
|
|
74
|
-
| `HlmStepperImports`
|
|
75
|
-
| `HlmStepperModule`
|
|
76
|
-
| `provideHlmStepperConfig
|
|
77
|
-
| `injectHlmStepperConfig`
|
|
66
|
+
| Symbol | Kind | Description |
|
|
67
|
+
| ------------------------- | ------------- | ------------------------------------------------------------------------- |
|
|
68
|
+
| `HlmStepper` | Component | Root: `<hlm-stepper>` — extends `CdkStepper`. |
|
|
69
|
+
| `HlmStep` | Component | Step: `<hlm-step label="…">` — extends `CdkStep`, adds `icon` input. |
|
|
70
|
+
| `HlmStepHeader` | Component | Header: `<hlm-step-header>` — extends `CdkStepHeader`, renders indicator. |
|
|
71
|
+
| `HlmStepLabel` | Directive | Rich label: `<ng-template hlmStepLabel>` — extends `CdkStepLabel`. |
|
|
72
|
+
| `HlmStepContent` | Directive | Lazy body: `<ng-template hlmStepContent>` — attached on first selection. |
|
|
73
|
+
| `HlmStepperNext` | Directive | Next button: `button[hlmStepperNext]` — extends `CdkStepperNext`. |
|
|
74
|
+
| `HlmStepperPrevious` | Directive | Back button: `button[hlmStepperPrevious]` — extends `CdkStepperPrevious`. |
|
|
75
|
+
| `HlmStepperImports` | `const` array | All seven, spread into `imports: [...]`. |
|
|
76
|
+
| `HlmStepperModule` | NgModule | Imports + re-exports all seven. |
|
|
77
|
+
| `provideHlmStepperConfig` | Function | Global defaults for animations + indicator mode. |
|
|
78
|
+
| `injectHlmStepperConfig` | Function | Reads the (optionally provided) global config. |
|
|
78
79
|
|
|
79
80
|
## Anatomy / Structure
|
|
80
81
|
|
|
@@ -122,47 +123,50 @@ Lazy body (attached only when the step is first selected):
|
|
|
122
123
|
|
|
123
124
|
### `HlmStepper` — selector `hlm-stepper` (component, extends `CdkStepper`)
|
|
124
125
|
|
|
125
|
-
| Input
|
|
126
|
-
|
|
|
127
|
-
| `orientation`
|
|
128
|
-
| `linear`
|
|
129
|
-
| `selectedIndex`
|
|
130
|
-
| `labelPosition`
|
|
131
|
-
| `headerPosition`
|
|
132
|
-
| `indicatorMode`
|
|
133
|
-
| `stepperAriaLabel`
|
|
134
|
-
| `stepperAriaLabelledby` | `string \| null`
|
|
135
|
-
| `animationsEnabled`
|
|
136
|
-
| `animationDuration`
|
|
126
|
+
| Input | Type | Default | Description |
|
|
127
|
+
| ----------------------- | ------------------------------- | ----------------------- | ---------------------------------------------------------------- |
|
|
128
|
+
| `orientation` | forwarded to `CdkStepper` | — | `'horizontal' \| 'vertical'`. |
|
|
129
|
+
| `linear` | forwarded to `CdkStepper` | — | Current step must be valid (via `stepControl`) before advancing. |
|
|
130
|
+
| `selectedIndex` | forwarded to `CdkStepper` | — | Controlled selected-step index. |
|
|
131
|
+
| `labelPosition` | `'end' \| 'bottom'` | `'end'` | Horizontal layout: label beside vs. below the indicator. |
|
|
132
|
+
| `headerPosition` | `'top' \| 'bottom'` | `'top'` | Horizontal layout: headers above vs. below the content panel. |
|
|
133
|
+
| `indicatorMode` | `'number' \| 'state' \| 'icon'` | from config (`'state'`) | Indicator rendering (see below). |
|
|
134
|
+
| `stepperAriaLabel` | `string \| null` | `'Progress'` | `aria-label` for the tablist (ignored when labelledby is set). |
|
|
135
|
+
| `stepperAriaLabelledby` | `string \| null` | `null` | `aria-labelledby` for the tablist. |
|
|
136
|
+
| `animationsEnabled` | `boolean` | from config (`true`) | Toggle step transitions per instance. |
|
|
137
|
+
| `animationDuration` | `number` (ms) | from config (`300`) | Transition duration per instance. |
|
|
137
138
|
|
|
138
139
|
`next()` is overridden to `markAllAsTouched()` + `updateValueAndValidity()` on the current `stepControl` first, so linear steppers surface validation errors before denying the transition.
|
|
139
140
|
|
|
140
141
|
### `HlmStep` — selector `hlm-step` (component, extends `CdkStep`)
|
|
141
142
|
|
|
142
|
-
| Input
|
|
143
|
-
|
|
|
144
|
-
| `label`
|
|
145
|
-
| `icon`
|
|
146
|
-
| `stepControl`
|
|
147
|
-
| `optional`
|
|
148
|
-
| `errorMessage
|
|
149
|
-
| `hasError`
|
|
143
|
+
| Input | Type | Default | Description |
|
|
144
|
+
| ----------------- | ---------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------ |
|
|
145
|
+
| `label` | forwarded to `CdkStep` | — | Step title (string, or rich template via `hlmStepLabel`). |
|
|
146
|
+
| `icon` | `string \| null` | `null` | Icon name rendered when `indicatorMode="icon"`. |
|
|
147
|
+
| `stepControl` | forwarded to `CdkStep` | — | Form group driving `linear` validation. |
|
|
148
|
+
| `optional` | forwarded to `CdkStep` | — | Shows an "Optional" caption in the header. |
|
|
149
|
+
| `errorMessage` | forwarded to `CdkStep` | — | Header error caption when the step state is `error`. |
|
|
150
|
+
| `hasError` | forwarded to `CdkStep` | — | Forces the error state (pair with `STEPPER_GLOBAL_OPTIONS` `showError`). |
|
|
151
|
+
| `tooltip` | `string \| TemplateRef<unknown> \| null` | `null` (falls back to the full string label) | Styled header tooltip override; rich templates allowed. |
|
|
152
|
+
| `tooltipPosition` | `'top' \| 'right' \| 'bottom' \| 'left'` | `'bottom'` | Tooltip side. |
|
|
153
|
+
| `tooltipDisabled` | `boolean` | `false` | Disables the header tooltip for this step. |
|
|
150
154
|
|
|
151
155
|
### `HlmStepHeader` — selector `hlm-step-header` (component, extends `CdkStepHeader`)
|
|
152
156
|
|
|
153
157
|
Usually rendered by `HlmStepper` itself; use directly only for custom layouts.
|
|
154
158
|
|
|
155
|
-
| Input
|
|
156
|
-
|
|
|
157
|
-
| `index`
|
|
158
|
-
| `state`
|
|
159
|
-
| `label`
|
|
160
|
-
| `selected` / `reached` / `active` | `boolean`
|
|
161
|
-
| `optional` / `disabled`
|
|
162
|
-
| `icon`
|
|
163
|
-
| `indicatorMode`
|
|
164
|
-
| `labelPosition`
|
|
165
|
-
| `errorMessage`
|
|
159
|
+
| Input | Type | Default | Description |
|
|
160
|
+
| --------------------------------- | -------------------------------- | ----------------------- | ------------------------------------------------------ |
|
|
161
|
+
| `index` | `number` | `0` | Step index (drives the number indicator). |
|
|
162
|
+
| `state` | `StepState` | `'number'` | CDK step state (`number`, `edit`, `done`, `error`, …). |
|
|
163
|
+
| `label` | `HlmStepLabel \| string \| null` | `null` | Resolved label content. |
|
|
164
|
+
| `selected` / `reached` / `active` | `boolean` | `false` | Visual state flags. |
|
|
165
|
+
| `optional` / `disabled` | `boolean` | `false` | Optional caption / disabled styling. |
|
|
166
|
+
| `icon` | `string \| null` | `null` | Icon name for `indicatorMode="icon"`. |
|
|
167
|
+
| `indicatorMode` | `'number' \| 'state' \| 'icon'` | from config (`'state'`) | Indicator rendering. |
|
|
168
|
+
| `labelPosition` | `'end' \| 'bottom'` | `'end'` | Label beside vs. below the indicator. |
|
|
169
|
+
| `errorMessage` | `string` | `''` | Error caption shown when `state === 'error'`. |
|
|
166
170
|
|
|
167
171
|
Indicator modes: `number` always renders `1, 2, 3`; `state` (default) renders a check icon for selected/reached steps and an alert icon for errors; `icon` renders the per-step `icon` name (provide icons via `@ng-icons/core` `provideIcons` in your app).
|
|
168
172
|
|
|
@@ -177,7 +181,9 @@ import { provideHlmStepperConfig } from '@egose/shadcn-theme-ng/stepper';
|
|
|
177
181
|
|
|
178
182
|
@Component({
|
|
179
183
|
// ...
|
|
180
|
-
providers: [
|
|
184
|
+
providers: [
|
|
185
|
+
provideHlmStepperConfig({ animationEnabled: true, animationDuration: 300, defaultIndicatorMode: 'state' }),
|
|
186
|
+
],
|
|
181
187
|
})
|
|
182
188
|
export class FeatureComponent {}
|
|
183
189
|
```
|
|
@@ -239,13 +245,14 @@ import { Component, computed, inject } from '@angular/core';
|
|
|
239
245
|
import { toSignal } from '@angular/core/rxjs-interop';
|
|
240
246
|
import { map } from 'rxjs/operators';
|
|
241
247
|
|
|
242
|
-
@Component({
|
|
248
|
+
@Component({
|
|
249
|
+
/* … */
|
|
250
|
+
})
|
|
243
251
|
export class DemoResponsive {
|
|
244
252
|
private readonly _breakpoints = inject(BreakpointObserver);
|
|
245
|
-
private readonly _isSmall = toSignal(
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
);
|
|
253
|
+
private readonly _isSmall = toSignal(this._breakpoints.observe('(max-width: 767.98px)').pipe(map((s) => s.matches)), {
|
|
254
|
+
initialValue: false,
|
|
255
|
+
});
|
|
249
256
|
protected readonly orientation = computed(() => (this._isSmall() ? 'vertical' : 'horizontal'));
|
|
250
257
|
}
|
|
251
258
|
```
|
|
@@ -262,7 +269,9 @@ With `linear`, the current step must be valid before advancing — `HlmStepper.n
|
|
|
262
269
|
import { Component, inject } from '@angular/core';
|
|
263
270
|
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
264
271
|
|
|
265
|
-
@Component({
|
|
272
|
+
@Component({
|
|
273
|
+
/* …, imports: [ReactiveFormsModule, ...HlmStepperImports, ...HlmButtonImports] */
|
|
274
|
+
})
|
|
266
275
|
export class DemoLinear {
|
|
267
276
|
private readonly _fb = inject(FormBuilder);
|
|
268
277
|
protected readonly identity = this._fb.group({ name: ['', Validators.required] });
|
|
@@ -334,6 +343,20 @@ Or set global defaults with `provideHlmStepperConfig` and override per instance.
|
|
|
334
343
|
|
|
335
344
|
Per-step `icon` names resolve through `@ng-icons/core` — register them with `provideIcons` in your app.
|
|
336
345
|
|
|
346
|
+
### 9. Header tooltips
|
|
347
|
+
|
|
348
|
+
Headers carry the styled `HlmTooltip` automatically: hovering or focusing a header shows the step's full string label (useful when labels truncate). Override per step with `tooltip` (plain text or a `TemplateRef`), adjust the side with `tooltipPosition`, or opt out with `tooltipDisabled`:
|
|
349
|
+
|
|
350
|
+
```html
|
|
351
|
+
<hlm-stepper>
|
|
352
|
+
<hlm-step label="An especially long account setup label that truncates"><!-- falls back to the label --></hlm-step>
|
|
353
|
+
<hlm-step label="Profile" tooltip="Add a photo so teammates recognize you"><!-- … --></hlm-step>
|
|
354
|
+
<hlm-step label="Review" [tooltipDisabled]="true"><!-- … --></hlm-step>
|
|
355
|
+
</hlm-stepper>
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
Steps using `<ng-template hlmStepLabel>` have no string to fall back to — pass `tooltip` explicitly if they need one. Custom `HlmStepHeader` layouts can apply `hlmTooltip` directly.
|
|
359
|
+
|
|
337
360
|
## Accessibility notes
|
|
338
361
|
|
|
339
362
|
- Horizontal headers get `role="tab"` semantics inside a `role="tablist"` (labelled `Progress` by default — override with `stepperAriaLabel` / `stepperAriaLabelledby`); panels get `role="tabpanel"` wired via `aria-labelledby` / `aria-controls`.
|