@egose/shadcn-theme-ng-tw 0.2.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 +1 -1
- package/alert/fesm2022/alert.mjs +1 -1
- package/autocomplete/fesm2022/autocomplete.mjs +1 -1
- package/button/fesm2022/button.mjs +3 -3
- package/checkbox/fesm2022/checkbox.mjs +6 -7
- package/checkbox/types/checkbox.d.ts +1 -1
- package/combobox/fesm2022/combobox.mjs +1 -1
- package/date-picker/README.md +15 -11
- package/date-picker/fesm2022/date-picker.mjs +148 -30
- package/date-picker/types/date-picker.d.ts +102 -9
- package/form-autocomplete/README.md +177 -0
- package/form-autocomplete/fesm2022/form-autocomplete.mjs +211 -0
- package/form-autocomplete/package.json +24 -0
- package/form-autocomplete/types/form-autocomplete.d.ts +61 -0
- package/form-checkbox/README.md +13 -3
- 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 +273 -0
- package/form-combobox/package.json +24 -0
- package/form-combobox/types/form-combobox.d.ts +73 -0
- package/form-date-picker/README.md +48 -22
- package/form-date-picker/fesm2022/form-date-picker.mjs +60 -16
- 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 +239 -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 +236 -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-input-otp/README.md +194 -0
- package/form-input-otp/fesm2022/form-input-otp.mjs +194 -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 +229 -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 +187 -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 +203 -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 +211 -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 +11 -1
- 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 +10 -0
- package/form-select/fesm2022/form-select.mjs +24 -15
- package/form-select/types/form-select.d.ts +18 -1
- package/form-slider/README.md +182 -0
- package/form-slider/fesm2022/form-slider.mjs +186 -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 +178 -0
- package/form-switch/package.json +24 -0
- package/form-switch/types/form-switch.d.ts +50 -0
- package/form-text-input/README.md +10 -0
- 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 +11 -1
- 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 +241 -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 +216 -0
- package/form-toggle-group/package.json +24 -0
- package/form-toggle-group/types/form-toggle-group.d.ts +65 -0
- package/input-group/fesm2022/input-group.mjs +20 -10
- package/input-group/types/input-group.d.ts +4 -1
- package/native-select/fesm2022/native-select.mjs +18 -6
- package/native-select/types/native-select.d.ts +7 -2
- package/package.json +57 -1
- 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/sheet/fesm2022/sheet.mjs +1 -1
- package/switch/fesm2022/switch.mjs +7 -5
- package/switch/types/switch.d.ts +2 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { forwardRef, inject, input, computed, booleanAttribute, linkedSignal, output, ChangeDetectionStrategy, Component, Directive, NgModule } from '@angular/core';
|
|
2
|
+
import { forwardRef, inject, input, computed, booleanAttribute, signal, linkedSignal, output, ChangeDetectionStrategy, Component, Directive, NgModule } from '@angular/core';
|
|
3
3
|
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
4
|
import { NgIcon, provideIcons } from '@ng-icons/core';
|
|
5
5
|
import { lucideChevronDown } from '@ng-icons/lucide';
|
|
@@ -17,9 +17,15 @@ class HlmNativeSelect {
|
|
|
17
17
|
static _id = 0;
|
|
18
18
|
selectId = input(`hlm-native-select-${HlmNativeSelect._id++}`, /* @ts-ignore */
|
|
19
19
|
...(ngDevMode ? [{ debugName: "selectId" }] : /* istanbul ignore next */ []));
|
|
20
|
+
/** Native `name` attribute forwarded to the inner `<select>`. */
|
|
21
|
+
name = input(undefined, /* @ts-ignore */
|
|
22
|
+
...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
23
|
+
/** ID of the element describing the select (error/hint) for assistive tech. */
|
|
24
|
+
ariaDescribedby = input(null, /* @ts-ignore */
|
|
25
|
+
...(ngDevMode ? [{ debugName: "ariaDescribedby" }] : /* istanbul ignore next */ []));
|
|
20
26
|
selectClass = input('', /* @ts-ignore */
|
|
21
27
|
...(ngDevMode ? [{ debugName: "selectClass" }] : /* istanbul ignore next */ []));
|
|
22
|
-
_computedSelectClass = computed(() => hlm('tw:border-input tw:placeholder:text-muted-foreground tw:selection:bg-primary tw:selection:text-primary-foreground tw:dark:bg-input/30 tw:dark:hover:bg-input/50 tw:focus-visible:border-ring tw:focus-visible:ring-ring/50 tw:data-[matches-spartan-invalid=true]:ring-destructive/20 tw:dark:data-[matches-spartan-invalid=true]:ring-destructive/40 tw:data-[matches-spartan-invalid=true]:border-destructive tw:dark:data-[matches-spartan-invalid=true]:border-destructive/50 tw:h-9 tw:w-full tw:min-w-0 tw:appearance-none tw:rounded-md tw:border tw:bg-transparent tw:py-1 tw:ps-2.5 tw:pe-8 tw:text-sm tw:shadow-xs tw:transition-[color,box-shadow] tw:select-none tw:focus-visible:ring-3 tw:data-[matches-spartan-invalid=true]:ring-3 tw:data-[size=sm]:h-8 tw:outline-none tw:disabled:pointer-events-none tw:disabled:cursor-not-allowed', this.selectClass()), /* @ts-ignore */
|
|
28
|
+
_computedSelectClass = computed(() => hlm('tw:border-input tw:placeholder:text-muted-foreground tw:selection:bg-primary tw:selection:text-primary-foreground tw:dark:bg-input/30 tw:dark:hover:bg-input/50 tw:focus-visible:border-ring tw:focus-visible:ring-ring/50 tw:data-[matches-spartan-invalid=true]:ring-destructive/20 tw:dark:data-[matches-spartan-invalid=true]:ring-destructive/40 tw:data-[matches-spartan-invalid=true]:border-destructive tw:dark:data-[matches-spartan-invalid=true]:border-destructive/50 tw:h-9 tw:w-full tw:min-w-0 tw:appearance-none tw:rounded-md tw:border tw:bg-transparent tw:py-1 tw:ps-2.5 tw:pe-8 tw:text-sm tw:text-foreground tw:shadow-xs tw:transition-[color,box-shadow] tw:select-none tw:focus-visible:ring-3 tw:data-[matches-spartan-invalid=true]:ring-3 tw:data-[size=sm]:h-8 tw:outline-none tw:disabled:pointer-events-none tw:disabled:cursor-not-allowed tw:[color-scheme:light] tw:dark:[color-scheme:dark]', this.selectClass()), /* @ts-ignore */
|
|
23
29
|
...(ngDevMode ? [{ debugName: "_computedSelectClass" }] : /* istanbul ignore next */ []));
|
|
24
30
|
selectIconClass = input('', /* @ts-ignore */
|
|
25
31
|
...(ngDevMode ? [{ debugName: "selectIconClass" }] : /* istanbul ignore next */ []));
|
|
@@ -28,7 +34,9 @@ class HlmNativeSelect {
|
|
|
28
34
|
size = input('default', /* @ts-ignore */
|
|
29
35
|
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
30
36
|
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
31
|
-
|
|
37
|
+
_formDisabled = signal(false, /* @ts-ignore */
|
|
38
|
+
...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
|
|
39
|
+
_disabled = computed(() => this.disabled() || this._formDisabled(), /* @ts-ignore */
|
|
32
40
|
...(ngDevMode ? [{ debugName: "_disabled" }] : /* istanbul ignore next */ []));
|
|
33
41
|
/** Whether to force the input into an invalid state. */
|
|
34
42
|
forceInvalid = input(false, { ...(ngDevMode ? { debugName: "forceInvalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
@@ -73,10 +81,10 @@ class HlmNativeSelect {
|
|
|
73
81
|
this._onTouched = fn;
|
|
74
82
|
}
|
|
75
83
|
setDisabledState(isDisabled) {
|
|
76
|
-
this.
|
|
84
|
+
this._formDisabled.set(isDisabled);
|
|
77
85
|
}
|
|
78
86
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmNativeSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
79
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.3", type: HlmNativeSelect, isStandalone: true, selector: "hlm-native-select", inputs: { selectId: { classPropertyName: "selectId", publicName: "selectId", isSignal: true, isRequired: false, transformFunction: null }, selectClass: { classPropertyName: "selectClass", publicName: "selectClass", isSignal: true, isRequired: false, transformFunction: null }, selectIconClass: { classPropertyName: "selectIconClass", publicName: "selectIconClass", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, forceInvalid: { classPropertyName: "forceInvalid", publicName: "forceInvalid", isSignal: true, isRequired: false, transformFunction: null }, ariaInvalidOverride: { classPropertyName: "ariaInvalidOverride", publicName: "aria-invalid", isSignal: true, isRequired: false, transformFunction: null }, valueInput: { classPropertyName: "valueInput", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { attributes: { "data-slot": "native-select-wrapper" }, properties: { "attr.data-size": "size()" } }, providers: [
|
|
87
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.3", type: HlmNativeSelect, isStandalone: true, selector: "hlm-native-select", inputs: { selectId: { classPropertyName: "selectId", publicName: "selectId", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedby: { classPropertyName: "ariaDescribedby", publicName: "ariaDescribedby", isSignal: true, isRequired: false, transformFunction: null }, selectClass: { classPropertyName: "selectClass", publicName: "selectClass", isSignal: true, isRequired: false, transformFunction: null }, selectIconClass: { classPropertyName: "selectIconClass", publicName: "selectIconClass", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, forceInvalid: { classPropertyName: "forceInvalid", publicName: "forceInvalid", isSignal: true, isRequired: false, transformFunction: null }, ariaInvalidOverride: { classPropertyName: "ariaInvalidOverride", publicName: "aria-invalid", isSignal: true, isRequired: false, transformFunction: null }, valueInput: { classPropertyName: "valueInput", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { attributes: { "data-slot": "native-select-wrapper" }, properties: { "attr.data-size": "size()" } }, providers: [
|
|
80
88
|
HLM_NATIVE_SELECT_VALUE_ACCESSOR,
|
|
81
89
|
provideIcons({ lucideChevronDown }),
|
|
82
90
|
provideBrnLabelable(HlmNativeSelect),
|
|
@@ -84,6 +92,8 @@ class HlmNativeSelect {
|
|
|
84
92
|
<select
|
|
85
93
|
data-slot="native-select"
|
|
86
94
|
[id]="selectId()"
|
|
95
|
+
[attr.name]="name()"
|
|
96
|
+
[attr.aria-describedby]="ariaDescribedby()"
|
|
87
97
|
[class]="_computedSelectClass()"
|
|
88
98
|
[attr.data-size]="size()"
|
|
89
99
|
[attr.aria-invalid]="_ariaInvalid() ? 'true' : null"
|
|
@@ -127,6 +137,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
127
137
|
<select
|
|
128
138
|
data-slot="native-select"
|
|
129
139
|
[id]="selectId()"
|
|
140
|
+
[attr.name]="name()"
|
|
141
|
+
[attr.aria-describedby]="ariaDescribedby()"
|
|
130
142
|
[class]="_computedSelectClass()"
|
|
131
143
|
[attr.data-size]="size()"
|
|
132
144
|
[attr.aria-invalid]="_ariaInvalid() ? 'true' : null"
|
|
@@ -150,7 +162,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
|
|
|
150
162
|
/>
|
|
151
163
|
`,
|
|
152
164
|
}]
|
|
153
|
-
}], ctorParameters: () => [], propDecorators: { selectId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectId", required: false }] }], selectClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectClass", required: false }] }], selectIconClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectIconClass", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], forceInvalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "forceInvalid", required: false }] }], ariaInvalidOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-invalid", required: false }] }], valueInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
165
|
+
}], ctorParameters: () => [], propDecorators: { selectId: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectId", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], ariaDescribedby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedby", required: false }] }], selectClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectClass", required: false }] }], selectIconClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectIconClass", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], forceInvalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "forceInvalid", required: false }] }], ariaInvalidOverride: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-invalid", required: false }] }], valueInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
154
166
|
|
|
155
167
|
class HlmNativeSelectOptGroup {
|
|
156
168
|
constructor() {
|
|
@@ -14,13 +14,18 @@ declare class HlmNativeSelect implements ControlValueAccessor {
|
|
|
14
14
|
private readonly _fieldControl;
|
|
15
15
|
private static _id;
|
|
16
16
|
readonly selectId: _angular_core.InputSignal<string>;
|
|
17
|
+
/** Native `name` attribute forwarded to the inner `<select>`. */
|
|
18
|
+
readonly name: _angular_core.InputSignal<string | undefined>;
|
|
19
|
+
/** ID of the element describing the select (error/hint) for assistive tech. */
|
|
20
|
+
readonly ariaDescribedby: _angular_core.InputSignal<string | null>;
|
|
17
21
|
readonly selectClass: _angular_core.InputSignal<ClassValue>;
|
|
18
22
|
protected readonly _computedSelectClass: _angular_core.Signal<string>;
|
|
19
23
|
readonly selectIconClass: _angular_core.InputSignal<ClassValue>;
|
|
20
24
|
protected readonly _computedSelectIconClass: _angular_core.Signal<string>;
|
|
21
25
|
readonly size: _angular_core.InputSignal<"sm" | "default">;
|
|
22
26
|
readonly disabled: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
23
|
-
|
|
27
|
+
private readonly _formDisabled;
|
|
28
|
+
protected readonly _disabled: _angular_core.Signal<boolean>;
|
|
24
29
|
/** Whether to force the input into an invalid state. */
|
|
25
30
|
readonly forceInvalid: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
26
31
|
/** Manual override for aria-invalid. When not set, auto-detects from the parent autocomplete error state. */
|
|
@@ -45,7 +50,7 @@ declare class HlmNativeSelect implements ControlValueAccessor {
|
|
|
45
50
|
registerOnTouched(fn: TouchFn): void;
|
|
46
51
|
setDisabledState(isDisabled: boolean): void;
|
|
47
52
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HlmNativeSelect, never>;
|
|
48
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<HlmNativeSelect, "hlm-native-select", never, { "selectId": { "alias": "selectId"; "required": false; "isSignal": true; }; "selectClass": { "alias": "selectClass"; "required": false; "isSignal": true; }; "selectIconClass": { "alias": "selectIconClass"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "forceInvalid": { "alias": "forceInvalid"; "required": false; "isSignal": true; }; "ariaInvalidOverride": { "alias": "aria-invalid"; "required": false; "isSignal": true; }; "valueInput": { "alias": "value"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, ["*"], true, [{ directive: typeof i1.BrnFieldControl; inputs: {}; outputs: {}; }]>;
|
|
53
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<HlmNativeSelect, "hlm-native-select", never, { "selectId": { "alias": "selectId"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "ariaDescribedby": { "alias": "ariaDescribedby"; "required": false; "isSignal": true; }; "selectClass": { "alias": "selectClass"; "required": false; "isSignal": true; }; "selectIconClass": { "alias": "selectIconClass"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "forceInvalid": { "alias": "forceInvalid"; "required": false; "isSignal": true; }; "ariaInvalidOverride": { "alias": "aria-invalid"; "required": false; "isSignal": true; }; "valueInput": { "alias": "value"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; }, never, ["*"], true, [{ directive: typeof i1.BrnFieldControl; inputs: {}; outputs: {}; }]>;
|
|
49
54
|
}
|
|
50
55
|
|
|
51
56
|
declare class HlmNativeSelectOptGroup {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@egose/shadcn-theme-ng-tw",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Angular shadcn UI theme",
|
|
5
5
|
"author": "Junmin Ahn",
|
|
6
6
|
"bundles": [
|
|
@@ -150,14 +150,30 @@
|
|
|
150
150
|
"types": "./field/types/field.d.ts",
|
|
151
151
|
"default": "./field/fesm2022/field.mjs"
|
|
152
152
|
},
|
|
153
|
+
"./form-autocomplete": {
|
|
154
|
+
"types": "./form-autocomplete/types/form-autocomplete.d.ts",
|
|
155
|
+
"default": "./form-autocomplete/fesm2022/form-autocomplete.mjs"
|
|
156
|
+
},
|
|
153
157
|
"./form-checkbox": {
|
|
154
158
|
"types": "./form-checkbox/types/form-checkbox.d.ts",
|
|
155
159
|
"default": "./form-checkbox/fesm2022/form-checkbox.mjs"
|
|
156
160
|
},
|
|
161
|
+
"./form-combobox": {
|
|
162
|
+
"types": "./form-combobox/types/form-combobox.d.ts",
|
|
163
|
+
"default": "./form-combobox/fesm2022/form-combobox.mjs"
|
|
164
|
+
},
|
|
157
165
|
"./form-date-picker": {
|
|
158
166
|
"types": "./form-date-picker/types/form-date-picker.d.ts",
|
|
159
167
|
"default": "./form-date-picker/fesm2022/form-date-picker.mjs"
|
|
160
168
|
},
|
|
169
|
+
"./form-date-picker-multi": {
|
|
170
|
+
"types": "./form-date-picker-multi/types/form-date-picker-multi.d.ts",
|
|
171
|
+
"default": "./form-date-picker-multi/fesm2022/form-date-picker-multi.mjs"
|
|
172
|
+
},
|
|
173
|
+
"./form-date-range-picker": {
|
|
174
|
+
"types": "./form-date-range-picker/types/form-date-range-picker.d.ts",
|
|
175
|
+
"default": "./form-date-range-picker/fesm2022/form-date-range-picker.mjs"
|
|
176
|
+
},
|
|
161
177
|
"./form-field": {
|
|
162
178
|
"types": "./form-field/types/form-field.d.ts",
|
|
163
179
|
"default": "./form-field/fesm2022/form-field.mjs"
|
|
@@ -166,6 +182,26 @@
|
|
|
166
182
|
"types": "./form-field-simple/types/form-field-simple.d.ts",
|
|
167
183
|
"default": "./form-field-simple/fesm2022/form-field-simple.mjs"
|
|
168
184
|
},
|
|
185
|
+
"./form-input-otp": {
|
|
186
|
+
"types": "./form-input-otp/types/form-input-otp.d.ts",
|
|
187
|
+
"default": "./form-input-otp/fesm2022/form-input-otp.mjs"
|
|
188
|
+
},
|
|
189
|
+
"./form-month-year-picker": {
|
|
190
|
+
"types": "./form-month-year-picker/types/form-month-year-picker.d.ts",
|
|
191
|
+
"default": "./form-month-year-picker/fesm2022/form-month-year-picker.mjs"
|
|
192
|
+
},
|
|
193
|
+
"./form-native-select": {
|
|
194
|
+
"types": "./form-native-select/types/form-native-select.d.ts",
|
|
195
|
+
"default": "./form-native-select/fesm2022/form-native-select.mjs"
|
|
196
|
+
},
|
|
197
|
+
"./form-phone-input": {
|
|
198
|
+
"types": "./form-phone-input/types/form-phone-input.d.ts",
|
|
199
|
+
"default": "./form-phone-input/fesm2022/form-phone-input.mjs"
|
|
200
|
+
},
|
|
201
|
+
"./form-radio-group": {
|
|
202
|
+
"types": "./form-radio-group/types/form-radio-group.d.ts",
|
|
203
|
+
"default": "./form-radio-group/fesm2022/form-radio-group.mjs"
|
|
204
|
+
},
|
|
169
205
|
"./form-searchable-multiselect": {
|
|
170
206
|
"types": "./form-searchable-multiselect/types/form-searchable-multiselect.d.ts",
|
|
171
207
|
"default": "./form-searchable-multiselect/fesm2022/form-searchable-multiselect.mjs"
|
|
@@ -174,6 +210,14 @@
|
|
|
174
210
|
"types": "./form-select/types/form-select.d.ts",
|
|
175
211
|
"default": "./form-select/fesm2022/form-select.mjs"
|
|
176
212
|
},
|
|
213
|
+
"./form-slider": {
|
|
214
|
+
"types": "./form-slider/types/form-slider.d.ts",
|
|
215
|
+
"default": "./form-slider/fesm2022/form-slider.mjs"
|
|
216
|
+
},
|
|
217
|
+
"./form-switch": {
|
|
218
|
+
"types": "./form-switch/types/form-switch.d.ts",
|
|
219
|
+
"default": "./form-switch/fesm2022/form-switch.mjs"
|
|
220
|
+
},
|
|
177
221
|
"./form-text-input": {
|
|
178
222
|
"types": "./form-text-input/types/form-text-input.d.ts",
|
|
179
223
|
"default": "./form-text-input/fesm2022/form-text-input.mjs"
|
|
@@ -182,6 +226,14 @@
|
|
|
182
226
|
"types": "./form-textarea/types/form-textarea.d.ts",
|
|
183
227
|
"default": "./form-textarea/fesm2022/form-textarea.mjs"
|
|
184
228
|
},
|
|
229
|
+
"./form-toggle": {
|
|
230
|
+
"types": "./form-toggle/types/form-toggle.d.ts",
|
|
231
|
+
"default": "./form-toggle/fesm2022/form-toggle.mjs"
|
|
232
|
+
},
|
|
233
|
+
"./form-toggle-group": {
|
|
234
|
+
"types": "./form-toggle-group/types/form-toggle-group.d.ts",
|
|
235
|
+
"default": "./form-toggle-group/fesm2022/form-toggle-group.mjs"
|
|
236
|
+
},
|
|
185
237
|
"./hover-card": {
|
|
186
238
|
"types": "./hover-card/types/hover-card.d.ts",
|
|
187
239
|
"default": "./hover-card/fesm2022/hover-card.mjs"
|
|
@@ -238,6 +290,10 @@
|
|
|
238
290
|
"types": "./pagination/types/pagination.d.ts",
|
|
239
291
|
"default": "./pagination/fesm2022/pagination.mjs"
|
|
240
292
|
},
|
|
293
|
+
"./phone-input": {
|
|
294
|
+
"types": "./phone-input/types/phone-input.d.ts",
|
|
295
|
+
"default": "./phone-input/fesm2022/phone-input.mjs"
|
|
296
|
+
},
|
|
241
297
|
"./popover": {
|
|
242
298
|
"types": "./popover/types/popover.d.ts",
|
|
243
299
|
"default": "./popover/fesm2022/popover.mjs"
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Phone Input (`@egose/shadcn-theme-ng/phone-input`)
|
|
2
|
+
|
|
3
|
+
A masked phone-number input. The form model holds raw digits (`"4155552671"`); the visible text is formatted (`"(415) 555-2671"`). Caret position is preserved across mask characters while typing or deleting — no DOM-selector lookups, no manual control subscriptions.
|
|
4
|
+
|
|
5
|
+
> **Ships as:** `@egose/shadcn-theme-ng/phone-input` and `@egose/shadcn-theme-ng-tw/phone-input`
|
|
6
|
+
> (the `tw:`-prefixed Tailwind variant). Both expose the identical TypeScript surface; only the
|
|
7
|
+
> emitted Tailwind class strings differ. See the [package README](../../README.md) for install
|
|
8
|
+
> steps, peer dependencies, and Tailwind setup. Do not publish this project directory independently.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Plain Tailwind (no prefix)
|
|
14
|
+
npm install @egose/shadcn-theme-ng
|
|
15
|
+
|
|
16
|
+
# tw:-prefixed Tailwind variant
|
|
17
|
+
npm install @egose/shadcn-theme-ng-tw
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Imports
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { HlmPhoneInput, formatNanpPhoneNumber, type PhoneNumberFormatter } from '@egose/shadcn-theme-ng/phone-input';
|
|
24
|
+
// tw variant: replace with '@egose/shadcn-theme-ng-tw/phone-input'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`HlmPhoneInput` implements `ControlValueAccessor`: bind it with `formControlName`, `formControl`, or `ngModel`. Prefer `EgFormPhoneInput` (`@egose/shadcn-theme-ng/form-phone-input`) for the label/error/hint wrapper.
|
|
28
|
+
|
|
29
|
+
## API reference
|
|
30
|
+
|
|
31
|
+
### `HlmPhoneInput` — `hlm-phone-input`
|
|
32
|
+
|
|
33
|
+
| Input | Type | Default | Description |
|
|
34
|
+
| ------------------- | ---------------------------- | ----------------------- | -------------------------------------------------- |
|
|
35
|
+
| `inputId` | `string` | `hlm-phone-input-<n>` | Native input id. |
|
|
36
|
+
| `name` | `string \| undefined` | — | Native `name` forwarded to the inner `<input>`. |
|
|
37
|
+
| `ariaLabel` | `string \| undefined` | — | Accessible label. |
|
|
38
|
+
| `ariaDescribedby` | `string \| null` | `null` | ID of the describing element. |
|
|
39
|
+
| `placeholder` | `string` | `''` | Input placeholder. |
|
|
40
|
+
| `autocomplete` | `string` | `'tel'` | Native autocomplete token. |
|
|
41
|
+
| `readonly` | `boolean` | `false` | Native `readonly` state. |
|
|
42
|
+
| `disabled` | `boolean` | `false` | Interaction lock (form control stays enabled). |
|
|
43
|
+
| `forceInvalid` | `boolean` | `false` | Forces invalid styling. |
|
|
44
|
+
| `maxDigits` | `number` | `10` | Maximum digit count kept in the model. |
|
|
45
|
+
| `modelFormat` | `'digits' \| 'formatted'` | `'digits'` | Model shape: raw digits or formatted display text. |
|
|
46
|
+
| `formatPhoneNumber` | `(digits: string) => string` | `formatNanpPhoneNumber` | Display formatter; receives raw digits. |
|
|
47
|
+
| `class` | `ClassValue` | `''` | Extra classes on the inner `<input>`. |
|
|
48
|
+
| `inputClass` | `ClassValue` | `''` | Extra classes on the inner `<input>`. |
|
|
49
|
+
|
|
50
|
+
Model values may be `string | null | undefined`; non-digit characters are stripped defensively on write. An empty model renders as empty text (no dangling mask characters) and emits `null`. With `modelFormat: 'formatted'` the model holds display text instead of digits — useful when a backend expects the masked value; validators then apply to the formatted string.
|
|
51
|
+
|
|
52
|
+
### `formatNanpPhoneNumber(digits)`
|
|
53
|
+
|
|
54
|
+
North-American numbering plan formatter: `4` → `(4`, `4155` → `(415) 5`, `4155552671` → `(415) 555-2671`, truncated to 10 digits. Pass a custom `PhoneNumberFormatter` for other plans (e.g. chunk-and-join national formats) together with a matching `maxDigits`.
|
|
55
|
+
|
|
56
|
+
## Examples
|
|
57
|
+
|
|
58
|
+
### 1. Standalone with formControl
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { Component, inject } from '@angular/core';
|
|
62
|
+
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
63
|
+
import { HlmPhoneInput } from '@egose/shadcn-theme-ng/phone-input';
|
|
64
|
+
|
|
65
|
+
@Component({
|
|
66
|
+
selector: 'app-callback',
|
|
67
|
+
standalone: true,
|
|
68
|
+
imports: [ReactiveFormsModule, HlmPhoneInput],
|
|
69
|
+
template: `
|
|
70
|
+
<form [formGroup]="form">
|
|
71
|
+
<label for="callback-phone">Callback number</label>
|
|
72
|
+
<hlm-phone-input formControlName="phone" inputId="callback-phone" />
|
|
73
|
+
</form>
|
|
74
|
+
<p>Digits: {{ form.value.phone ?? '—' }}</p>
|
|
75
|
+
`,
|
|
76
|
+
})
|
|
77
|
+
export class CallbackComponent {
|
|
78
|
+
private readonly fb = inject(FormBuilder);
|
|
79
|
+
readonly form = this.fb.group({ phone: ['', [Validators.required, Validators.minLength(10)]] });
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 2. Custom format (UK-style 5+6 grouping)
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
@Component({
|
|
87
|
+
selector: 'app-uk-phone',
|
|
88
|
+
standalone: true,
|
|
89
|
+
imports: [ReactiveFormsModule, HlmPhoneInput],
|
|
90
|
+
template: ` <hlm-phone-input [formControl]="control" [formatPhoneNumber]="ukFormat" [maxDigits]="11" /> `,
|
|
91
|
+
})
|
|
92
|
+
export class UkPhoneComponent {
|
|
93
|
+
readonly control = new FormControl<string | null>(null);
|
|
94
|
+
readonly ukFormat = (digits: string) => {
|
|
95
|
+
const d = digits.replace(/\D/g, '').slice(0, 11);
|
|
96
|
+
if (d.length <= 5) return d;
|
|
97
|
+
return `${d.slice(0, 5)} ${d.slice(5)}`;
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Accessibility notes
|
|
103
|
+
|
|
104
|
+
- Wire a `<label for>` to `inputId`; pass `ariaLabel`/`ariaDescribedby` when composing manually (the `eg-form-phone-input` wrapper does this automatically).
|
|
105
|
+
- Keep `autocomplete="tel"` (the default) so password managers and mobile keyboards offer phone autofill.
|
|
106
|
+
|
|
107
|
+
## Theming / CSS variables
|
|
108
|
+
|
|
109
|
+
No component-specific CSS variables; the inner input carries the shared `HlmInput` base. Append utilities via `class` / `inputClass`.
|
|
110
|
+
|
|
111
|
+
## Related subpaths
|
|
112
|
+
|
|
113
|
+
- `@egose/shadcn-theme-ng/form-phone-input` — `eg-form-phone-input` label/error/hint wrapper.
|
|
114
|
+
- `@egose/shadcn-theme-ng/input` — `hlmInput` directive styling the inner input.
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { forwardRef, input, booleanAttribute, computed, signal, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
|
+
import * as i1 from '@spartan-ng/brain/field';
|
|
5
|
+
import { BrnFieldControl } from '@spartan-ng/brain/field';
|
|
6
|
+
import { HlmInput } from '@egose/shadcn-theme-ng-tw/input';
|
|
7
|
+
import { hlm } from '@egose/shadcn-theme-ng-tw/utils';
|
|
8
|
+
|
|
9
|
+
const HLM_PHONE_INPUT_VALUE_ACCESSOR = {
|
|
10
|
+
provide: NG_VALUE_ACCESSOR,
|
|
11
|
+
useExisting: forwardRef(() => HlmPhoneInput),
|
|
12
|
+
multi: true,
|
|
13
|
+
};
|
|
14
|
+
function formatNanpPhoneNumber(digits) {
|
|
15
|
+
const d = digits.replace(/\D/g, '').slice(0, 10);
|
|
16
|
+
if (d.length === 0)
|
|
17
|
+
return '';
|
|
18
|
+
if (d.length <= 3)
|
|
19
|
+
return `(${d}`;
|
|
20
|
+
if (d.length <= 6)
|
|
21
|
+
return `(${d.slice(0, 3)}) ${d.slice(3)}`;
|
|
22
|
+
return `(${d.slice(0, 3)}) ${d.slice(3, 6)}-${d.slice(6)}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A masked phone input. The form model holds raw digits (`"4155552671"`);
|
|
26
|
+
* the visible text is formatted (`"(415) 555-2671"`). Caret position is
|
|
27
|
+
* preserved across mask characters while typing or deleting.
|
|
28
|
+
*/
|
|
29
|
+
class HlmPhoneInput {
|
|
30
|
+
static _id = 0;
|
|
31
|
+
inputId = input(`hlm-phone-input-${HlmPhoneInput._id++}`, /* @ts-ignore */
|
|
32
|
+
...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
|
|
33
|
+
name = input(undefined, /* @ts-ignore */
|
|
34
|
+
...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
35
|
+
ariaLabel = input(undefined, /* @ts-ignore */
|
|
36
|
+
...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
37
|
+
ariaDescribedby = input(null, /* @ts-ignore */
|
|
38
|
+
...(ngDevMode ? [{ debugName: "ariaDescribedby" }] : /* istanbul ignore next */ []));
|
|
39
|
+
placeholder = input('', /* @ts-ignore */
|
|
40
|
+
...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
41
|
+
autocomplete = input('tel', /* @ts-ignore */
|
|
42
|
+
...(ngDevMode ? [{ debugName: "autocomplete" }] : /* istanbul ignore next */ []));
|
|
43
|
+
readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
44
|
+
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
45
|
+
forceInvalid = input(false, { ...(ngDevMode ? { debugName: "forceInvalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
46
|
+
/** Maximum digit count kept in the model. Defaults to 10 (NANP). */
|
|
47
|
+
maxDigits = input(10, /* @ts-ignore */
|
|
48
|
+
...(ngDevMode ? [{ debugName: "maxDigits" }] : /* istanbul ignore next */ []));
|
|
49
|
+
/**
|
|
50
|
+
* Shape of the form model: raw digits (`"4155552671"`, the default —
|
|
51
|
+
* validator- and storage-friendly) or formatted display text
|
|
52
|
+
* (`"(415) 555-2671"`).
|
|
53
|
+
*/
|
|
54
|
+
modelFormat = input('digits', /* @ts-ignore */
|
|
55
|
+
...(ngDevMode ? [{ debugName: "modelFormat" }] : /* istanbul ignore next */ []));
|
|
56
|
+
/** Display formatter. Receives raw digits, returns display text. */
|
|
57
|
+
formatPhoneNumber = input(formatNanpPhoneNumber, /* @ts-ignore */
|
|
58
|
+
...(ngDevMode ? [{ debugName: "formatPhoneNumber" }] : /* istanbul ignore next */ []));
|
|
59
|
+
/** Extra classes merged onto the inner `<input>` (over the `HlmInput` base). */
|
|
60
|
+
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
61
|
+
inputClass = input('', /* @ts-ignore */
|
|
62
|
+
...(ngDevMode ? [{ debugName: "inputClass" }] : /* istanbul ignore next */ []));
|
|
63
|
+
$inputClass = computed(() => hlm(this.userClass(), this.inputClass()), /* @ts-ignore */
|
|
64
|
+
...(ngDevMode ? [{ debugName: "$inputClass" }] : /* istanbul ignore next */ []));
|
|
65
|
+
_formDisabled = signal(false, /* @ts-ignore */
|
|
66
|
+
...(ngDevMode ? [{ debugName: "_formDisabled" }] : /* istanbul ignore next */ []));
|
|
67
|
+
disabledState = computed(() => this.disabled() || this._formDisabled(), /* @ts-ignore */
|
|
68
|
+
...(ngDevMode ? [{ debugName: "disabledState" }] : /* istanbul ignore next */ []));
|
|
69
|
+
/** Raw digits held in the form model. */
|
|
70
|
+
_digits = signal('', /* @ts-ignore */
|
|
71
|
+
...(ngDevMode ? [{ debugName: "_digits" }] : /* istanbul ignore next */ []));
|
|
72
|
+
/** Formatted text shown in the input. */
|
|
73
|
+
_display = computed(() => this.formatPhoneNumber()(this._digits()), /* @ts-ignore */
|
|
74
|
+
...(ngDevMode ? [{ debugName: "_display" }] : /* istanbul ignore next */ []));
|
|
75
|
+
_onChange;
|
|
76
|
+
_onTouched;
|
|
77
|
+
_emitModel(digits) {
|
|
78
|
+
if (digits === this._digits())
|
|
79
|
+
return;
|
|
80
|
+
this._digits.set(digits);
|
|
81
|
+
if (digits === '') {
|
|
82
|
+
this._onChange?.(null);
|
|
83
|
+
}
|
|
84
|
+
else if (this.modelFormat() === 'formatted') {
|
|
85
|
+
this._onChange?.(this.formatPhoneNumber()(digits));
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
this._onChange?.(digits);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
_handleInput(event) {
|
|
92
|
+
const element = event.target;
|
|
93
|
+
const caret = element.selectionStart ?? element.value.length;
|
|
94
|
+
const digitsBeforeCaret = element.value.slice(0, caret).replace(/\D/g, '').length;
|
|
95
|
+
const digits = element.value.replace(/\D/g, '').slice(0, Math.max(0, this.maxDigits()));
|
|
96
|
+
const formatted = this.formatPhoneNumber()(digits);
|
|
97
|
+
const target = Math.min(digitsBeforeCaret, digits.length);
|
|
98
|
+
let position = 0;
|
|
99
|
+
let seen = 0;
|
|
100
|
+
while (position < formatted.length && seen < target) {
|
|
101
|
+
if (/\d/.test(formatted[position]))
|
|
102
|
+
seen++;
|
|
103
|
+
position++;
|
|
104
|
+
}
|
|
105
|
+
element.value = formatted;
|
|
106
|
+
element.setSelectionRange(position, position);
|
|
107
|
+
this._emitModel(digits);
|
|
108
|
+
}
|
|
109
|
+
_handleBlur() {
|
|
110
|
+
this._onTouched?.();
|
|
111
|
+
}
|
|
112
|
+
/** CONTROL VALUE ACCESSOR */
|
|
113
|
+
writeValue(value) {
|
|
114
|
+
this._digits.set(String(value ?? '')
|
|
115
|
+
.replace(/\D/g, '')
|
|
116
|
+
.slice(0, Math.max(0, this.maxDigits())));
|
|
117
|
+
}
|
|
118
|
+
registerOnChange(fn) {
|
|
119
|
+
this._onChange = fn;
|
|
120
|
+
}
|
|
121
|
+
registerOnTouched(fn) {
|
|
122
|
+
this._onTouched = fn;
|
|
123
|
+
}
|
|
124
|
+
setDisabledState(isDisabled) {
|
|
125
|
+
this._formDisabled.set(isDisabled);
|
|
126
|
+
}
|
|
127
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmPhoneInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
128
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.3", type: HlmPhoneInput, isStandalone: true, selector: "hlm-phone-input", inputs: { inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaDescribedby: { classPropertyName: "ariaDescribedby", publicName: "ariaDescribedby", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", 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 }, forceInvalid: { classPropertyName: "forceInvalid", publicName: "forceInvalid", isSignal: true, isRequired: false, transformFunction: null }, maxDigits: { classPropertyName: "maxDigits", publicName: "maxDigits", isSignal: true, isRequired: false, transformFunction: null }, modelFormat: { classPropertyName: "modelFormat", publicName: "modelFormat", isSignal: true, isRequired: false, transformFunction: null }, formatPhoneNumber: { classPropertyName: "formatPhoneNumber", publicName: "formatPhoneNumber", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, inputClass: { classPropertyName: "inputClass", publicName: "inputClass", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-disabled": "disabledState() ? \"\" : null" }, classAttribute: "tw:block tw:w-full tw:min-w-0" }, providers: [HLM_PHONE_INPUT_VALUE_ACCESSOR], hostDirectives: [{ directive: i1.BrnFieldControl }], ngImport: i0, template: `
|
|
129
|
+
<input
|
|
130
|
+
#input
|
|
131
|
+
hlmInput
|
|
132
|
+
[id]="inputId()"
|
|
133
|
+
[attr.name]="name()"
|
|
134
|
+
[attr.aria-label]="ariaLabel()"
|
|
135
|
+
[attr.aria-describedby]="ariaDescribedby()"
|
|
136
|
+
[placeholder]="placeholder()"
|
|
137
|
+
[autocomplete]="autocomplete()"
|
|
138
|
+
[readonly]="readonly()"
|
|
139
|
+
[disabled]="disabledState()"
|
|
140
|
+
[forceInvalid]="forceInvalid()"
|
|
141
|
+
[class]="$inputClass()"
|
|
142
|
+
[value]="_display()"
|
|
143
|
+
(input)="_handleInput($event)"
|
|
144
|
+
(blur)="_handleBlur()"
|
|
145
|
+
/>
|
|
146
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: HlmInput, selector: "[hlmInput]", inputs: ["ariaDescribedby"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
147
|
+
}
|
|
148
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: HlmPhoneInput, decorators: [{
|
|
149
|
+
type: Component,
|
|
150
|
+
args: [{
|
|
151
|
+
selector: 'hlm-phone-input',
|
|
152
|
+
imports: [HlmInput],
|
|
153
|
+
providers: [HLM_PHONE_INPUT_VALUE_ACCESSOR],
|
|
154
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
155
|
+
hostDirectives: [BrnFieldControl],
|
|
156
|
+
host: {
|
|
157
|
+
class: 'tw:block tw:w-full tw:min-w-0',
|
|
158
|
+
'[attr.data-disabled]': 'disabledState() ? "" : null',
|
|
159
|
+
},
|
|
160
|
+
template: `
|
|
161
|
+
<input
|
|
162
|
+
#input
|
|
163
|
+
hlmInput
|
|
164
|
+
[id]="inputId()"
|
|
165
|
+
[attr.name]="name()"
|
|
166
|
+
[attr.aria-label]="ariaLabel()"
|
|
167
|
+
[attr.aria-describedby]="ariaDescribedby()"
|
|
168
|
+
[placeholder]="placeholder()"
|
|
169
|
+
[autocomplete]="autocomplete()"
|
|
170
|
+
[readonly]="readonly()"
|
|
171
|
+
[disabled]="disabledState()"
|
|
172
|
+
[forceInvalid]="forceInvalid()"
|
|
173
|
+
[class]="$inputClass()"
|
|
174
|
+
[value]="_display()"
|
|
175
|
+
(input)="_handleInput($event)"
|
|
176
|
+
(blur)="_handleBlur()"
|
|
177
|
+
/>
|
|
178
|
+
`,
|
|
179
|
+
}]
|
|
180
|
+
}], propDecorators: { inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaDescribedby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaDescribedby", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], forceInvalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "forceInvalid", required: false }] }], maxDigits: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDigits", required: false }] }], modelFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "modelFormat", required: false }] }], formatPhoneNumber: [{ type: i0.Input, args: [{ isSignal: true, alias: "formatPhoneNumber", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], inputClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputClass", required: false }] }] } });
|
|
181
|
+
|
|
182
|
+
/*
|
|
183
|
+
* Public API Surface of phone-input
|
|
184
|
+
*/
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Generated bundle index. Do not edit.
|
|
188
|
+
*/
|
|
189
|
+
|
|
190
|
+
export { HLM_PHONE_INPUT_VALUE_ACCESSOR, HlmPhoneInput, formatNanpPhoneNumber };
|
|
191
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "phone-input",
|
|
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/phone-input.mjs",
|
|
13
|
+
"typings": "types/phone-input.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
"./package.json": {
|
|
16
|
+
"default": "./package.json"
|
|
17
|
+
},
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./types/phone-input.d.ts",
|
|
20
|
+
"default": "./fesm2022/phone-input.mjs"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"type": "module"
|
|
24
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { ControlValueAccessor } from '@angular/forms';
|
|
3
|
+
import { BooleanInput } from '@angular/cdk/coercion';
|
|
4
|
+
import { ClassValue } from 'clsx';
|
|
5
|
+
import { ChangeFn, TouchFn } from '@spartan-ng/brain/forms';
|
|
6
|
+
import * as i1 from '@spartan-ng/brain/field';
|
|
7
|
+
|
|
8
|
+
declare const HLM_PHONE_INPUT_VALUE_ACCESSOR: {
|
|
9
|
+
provide: _angular_core.InjectionToken<readonly ControlValueAccessor[]>;
|
|
10
|
+
useExisting: _angular_core.Type<any>;
|
|
11
|
+
multi: boolean;
|
|
12
|
+
};
|
|
13
|
+
/** Formats digit strings for display. Defaults to NANP `(XXX) XXX-XXXX` with an open paren while typing. */
|
|
14
|
+
type PhoneNumberFormatter = (digits: string) => string;
|
|
15
|
+
declare function formatNanpPhoneNumber(digits: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* A masked phone input. The form model holds raw digits (`"4155552671"`);
|
|
18
|
+
* the visible text is formatted (`"(415) 555-2671"`). Caret position is
|
|
19
|
+
* preserved across mask characters while typing or deleting.
|
|
20
|
+
*/
|
|
21
|
+
declare class HlmPhoneInput implements ControlValueAccessor {
|
|
22
|
+
private static _id;
|
|
23
|
+
readonly inputId: _angular_core.InputSignal<string>;
|
|
24
|
+
readonly name: _angular_core.InputSignal<string | undefined>;
|
|
25
|
+
readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
|
|
26
|
+
readonly ariaDescribedby: _angular_core.InputSignal<string | null>;
|
|
27
|
+
readonly placeholder: _angular_core.InputSignal<string>;
|
|
28
|
+
readonly autocomplete: _angular_core.InputSignal<string>;
|
|
29
|
+
readonly readonly: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
30
|
+
readonly disabled: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
31
|
+
readonly forceInvalid: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
|
|
32
|
+
/** Maximum digit count kept in the model. Defaults to 10 (NANP). */
|
|
33
|
+
readonly maxDigits: _angular_core.InputSignal<number>;
|
|
34
|
+
/**
|
|
35
|
+
* Shape of the form model: raw digits (`"4155552671"`, the default —
|
|
36
|
+
* validator- and storage-friendly) or formatted display text
|
|
37
|
+
* (`"(415) 555-2671"`).
|
|
38
|
+
*/
|
|
39
|
+
readonly modelFormat: _angular_core.InputSignal<"digits" | "formatted">;
|
|
40
|
+
/** Display formatter. Receives raw digits, returns display text. */
|
|
41
|
+
readonly formatPhoneNumber: _angular_core.InputSignal<PhoneNumberFormatter>;
|
|
42
|
+
/** Extra classes merged onto the inner `<input>` (over the `HlmInput` base). */
|
|
43
|
+
readonly userClass: _angular_core.InputSignal<ClassValue>;
|
|
44
|
+
readonly inputClass: _angular_core.InputSignal<ClassValue>;
|
|
45
|
+
protected readonly $inputClass: _angular_core.Signal<string>;
|
|
46
|
+
private readonly _formDisabled;
|
|
47
|
+
protected readonly disabledState: _angular_core.Signal<boolean>;
|
|
48
|
+
/** Raw digits held in the form model. */
|
|
49
|
+
protected readonly _digits: _angular_core.WritableSignal<string>;
|
|
50
|
+
/** Formatted text shown in the input. */
|
|
51
|
+
protected readonly _display: _angular_core.Signal<string>;
|
|
52
|
+
protected _onChange?: ChangeFn<string | null>;
|
|
53
|
+
protected _onTouched?: TouchFn;
|
|
54
|
+
private _emitModel;
|
|
55
|
+
protected _handleInput(event: Event): void;
|
|
56
|
+
protected _handleBlur(): void;
|
|
57
|
+
/** CONTROL VALUE ACCESSOR */
|
|
58
|
+
writeValue(value: string | null | undefined): void;
|
|
59
|
+
registerOnChange(fn: ChangeFn<string | null>): void;
|
|
60
|
+
registerOnTouched(fn: TouchFn): void;
|
|
61
|
+
setDisabledState(isDisabled: boolean): void;
|
|
62
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HlmPhoneInput, never>;
|
|
63
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<HlmPhoneInput, "hlm-phone-input", never, { "inputId": { "alias": "inputId"; "required": false; "isSignal": true; }; "name": { "alias": "name"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "ariaDescribedby": { "alias": "ariaDescribedby"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "autocomplete": { "alias": "autocomplete"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "forceInvalid": { "alias": "forceInvalid"; "required": false; "isSignal": true; }; "maxDigits": { "alias": "maxDigits"; "required": false; "isSignal": true; }; "modelFormat": { "alias": "modelFormat"; "required": false; "isSignal": true; }; "formatPhoneNumber": { "alias": "formatPhoneNumber"; "required": false; "isSignal": true; }; "userClass": { "alias": "class"; "required": false; "isSignal": true; }; "inputClass": { "alias": "inputClass"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.BrnFieldControl; inputs: {}; outputs: {}; }]>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { HLM_PHONE_INPUT_VALUE_ACCESSOR, HlmPhoneInput, formatNanpPhoneNumber };
|
|
67
|
+
export type { PhoneNumberFormatter };
|