@tailng-ui/primitives 0.19.0 → 0.20.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/package.json +2 -2
- package/src/lib/form/input/tng-adornment.d.ts +2 -2
- package/src/lib/form/input/tng-adornment.d.ts.map +1 -1
- package/src/lib/form/input/tng-adornment.js +1 -1
- package/src/lib/form/input/tng-adornment.js.map +1 -1
- package/src/lib/form/input/tng-input-group.d.ts +2 -2
- package/src/lib/form/input/tng-input-group.d.ts.map +1 -1
- package/src/lib/form/input/tng-input-group.js +32 -25
- package/src/lib/form/input/tng-input-group.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailng-ui/primitives",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@tailng-ui/cdk": "^0.
|
|
19
|
+
"@tailng-ui/cdk": "^0.16.0"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"@angular/core": "^21.1.0",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as i0 from "@angular/core";
|
|
2
2
|
export declare class TngPrefix {
|
|
3
|
-
readonly hostElement:
|
|
3
|
+
readonly hostElement: HTMLElement;
|
|
4
4
|
protected readonly dataSlot: "input-leading";
|
|
5
5
|
static ɵfac: i0.ɵɵFactoryDeclaration<TngPrefix, never>;
|
|
6
6
|
static ɵdir: i0.ɵɵDirectiveDeclaration<TngPrefix, "[tngPrefix], [tngInputLeading]", ["tngPrefix"], {}, {}, never, never, true, never>;
|
|
7
7
|
}
|
|
8
8
|
export declare class TngSuffix {
|
|
9
|
-
readonly hostElement:
|
|
9
|
+
readonly hostElement: HTMLElement;
|
|
10
10
|
protected readonly dataSlot: "input-trailing";
|
|
11
11
|
static ɵfac: i0.ɵɵFactoryDeclaration<TngSuffix, never>;
|
|
12
12
|
static ɵdir: i0.ɵɵDirectiveDeclaration<TngSuffix, "[tngSuffix], [tngInputTrailing]", ["tngSuffix"], {}, {}, never, never, true, never>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tng-adornment.d.ts","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input/tng-adornment.ts"],"names":[],"mappings":";AAEA,qBAIa,SAAS;IACpB,
|
|
1
|
+
{"version":3,"file":"tng-adornment.d.ts","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input/tng-adornment.ts"],"names":[],"mappings":";AAEA,qBAIa,SAAS;IACpB,SAAgB,WAAW,EAAE,WAAW,CAAgE;IAGxG,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAG,eAAe,CAAU;yCAJ5C,SAAS;2CAAT,SAAS;CAKrB;AAED,qBAIa,SAAS;IACpB,SAAgB,WAAW,EAAE,WAAW,CAAgE;IAGxG,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAG,gBAAgB,CAAU;yCAJ7C,SAAS;2CAAT,SAAS;CAKrB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tng-adornment.js","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input/tng-adornment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;AAM3E,MAAM,OAAO,SAAS;
|
|
1
|
+
{"version":3,"file":"tng-adornment.js","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input/tng-adornment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;;AAM3E,MAAM,OAAO,SAAS;IACJ,WAAW,GAAgB,MAAM,CAAC,CAAA,UAAuB,CAAA,CAAC,CAAC,aAA4B,CAAC;IAGrF,QAAQ,GAAG,eAAwB,CAAC;uGAJ5C,SAAS;2FAAT,SAAS;;2FAAT,SAAS;kBAJrB,SAAS;mBAAC;oBACT,QAAQ,EAAE,gCAAgC;oBAC1C,QAAQ,EAAE,WAAW;iBACtB;;sBAIE,WAAW;uBAAC,gBAAgB;;AAQ/B,MAAM,OAAO,SAAS;IACJ,WAAW,GAAgB,MAAM,CAAC,CAAA,UAAuB,CAAA,CAAC,CAAC,aAA4B,CAAC;IAGrF,QAAQ,GAAG,gBAAyB,CAAC;uGAJ7C,SAAS;2FAAT,SAAS;;2FAAT,SAAS;kBAJrB,SAAS;mBAAC;oBACT,QAAQ,EAAE,iCAAiC;oBAC3C,QAAQ,EAAE,WAAW;iBACtB;;sBAIE,WAAW;uBAAC,gBAAgB","sourcesContent":["import { Directive, ElementRef, HostBinding, inject } from '@angular/core';\n\n@Directive({\n selector: '[tngPrefix], [tngInputLeading]',\n exportAs: 'tngPrefix',\n})\nexport class TngPrefix {\n public readonly hostElement: HTMLElement = inject(ElementRef<HTMLElement>).nativeElement as HTMLElement;\n\n @HostBinding('attr.data-slot')\n protected readonly dataSlot = 'input-leading' as const;\n}\n\n@Directive({\n selector: '[tngSuffix], [tngInputTrailing]',\n exportAs: 'tngSuffix',\n})\nexport class TngSuffix {\n public readonly hostElement: HTMLElement = inject(ElementRef<HTMLElement>).nativeElement as HTMLElement;\n\n @HostBinding('attr.data-slot')\n protected readonly dataSlot = 'input-trailing' as const;\n}\n"]}
|
|
@@ -26,7 +26,7 @@ export declare class TngInputGroup implements AfterContentInit, OnDestroy {
|
|
|
26
26
|
protected get dataReadonly(): '' | null;
|
|
27
27
|
protected get dataFocused(): '' | null;
|
|
28
28
|
protected onFocusIn(): void;
|
|
29
|
-
protected onFocusOut(
|
|
29
|
+
protected onFocusOut(nextTarget: Readonly<EventTarget> | null): void;
|
|
30
30
|
protected hasLeadingSlot(): boolean;
|
|
31
31
|
protected hasTrailingSlot(): boolean;
|
|
32
32
|
protected effectiveHasLeading(): boolean;
|
|
@@ -34,6 +34,6 @@ export declare class TngInputGroup implements AfterContentInit, OnDestroy {
|
|
|
34
34
|
protected primaryControl(): TngInput | null;
|
|
35
35
|
protected primaryControlElement(): HTMLInputElement | HTMLTextAreaElement | null;
|
|
36
36
|
static ɵfac: i0.ɵɵFactoryDeclaration<TngInputGroup, never>;
|
|
37
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<TngInputGroup, "tng-input-group, [tngInputGroup]", ["tngInputGroup"], { "hasLeading": { "alias": "hasLeading"; "required": false; "isSignal": true; }; "hasTrailing": { "alias": "hasTrailing"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "controlCount": { "alias": "controlCount"; "required": false; "isSignal": true; }; }, {}, ["controls", "prefixSlots", "suffixSlots"], ["[tngPrefix], [tngInputLeading], [data-tng-input-prefix-proxy]", "input[tngInput], textarea[tngInput], [data-tng-input-control-proxy]", "[tngSuffix], [tngInputTrailing], [data-tng-input-suffix-proxy]"], true, never>;
|
|
37
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<TngInputGroup, "tng-input-group, [tngInputGroup]", ["tngInputGroup"], { "hasLeading": { "alias": "hasLeading"; "required": false; "isSignal": true; }; "hasTrailing": { "alias": "hasTrailing"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "invalid": { "alias": "invalid"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "controlCount": { "alias": "controlCount"; "required": false; "isSignal": true; }; }, {}, ["controls", "prefixSlots", "suffixSlots"], ["[tngPrefix], [tngInputLeading], [data-tng-input-prefix-proxy]", "input[tngInput], textarea[tngInput], textarea[tngTextarea], [data-tng-input-control-proxy]", "[tngSuffix], [tngInputTrailing], [data-tng-input-suffix-proxy]"], true, never>;
|
|
38
38
|
}
|
|
39
39
|
//# sourceMappingURL=tng-input-group.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tng-input-group.d.ts","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input/tng-input-group.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAa5E,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;;
|
|
1
|
+
{"version":3,"file":"tng-input-group.d.ts","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input/tng-input-group.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAa5E,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;;AAMvC,qBA6Ca,aAAc,YAAW,gBAAgB,EAAE,SAAS;IAC/D,SAAgB,UAAU,sDAA+B;IACzD,SAAgB,WAAW,sDAA+B;IAC1D,SAAgB,QAAQ,sDAA+B;IACvD,SAAgB,OAAO,sDAA+B;IACtD,SAAgB,QAAQ,sDAA+B;IACvD,SAAgB,YAAY,qDAA8B;IAG1D,SAAS,CAAC,QAAQ,EAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IAGzC,SAAS,CAAC,WAAW,EAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IAG7C,SAAS,CAAC,WAAW,EAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IAE7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6E;IACzG,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAElD,OAAO,CAAC,qBAAqB;IAmBtB,kBAAkB,IAAI,IAAI;IAM1B,WAAW,IAAI,IAAI;IAM1B,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAG,aAAa,CAAU;IAGrD,SAAS,KAAK,cAAc,IAAI,EAAE,GAAG,IAAI,CAExC;IAGD,SAAS,KAAK,eAAe,IAAI,EAAE,GAAG,IAAI,CAEzC;IAGD,SAAS,KAAK,YAAY,IAAI,EAAE,GAAG,IAAI,CAUtC;IAGD,SAAS,KAAK,WAAW,IAAI,EAAE,GAAG,IAAI,CAWrC;IAGD,SAAS,KAAK,YAAY,IAAI,EAAE,GAAG,IAAI,CAUtC;IAGD,SAAS,KAAK,WAAW,IAAI,EAAE,GAAG,IAAI,CAErC;IAGD,SAAS,CAAC,SAAS,IAAI,IAAI;IAK3B,SAAS,CAAC,UAAU,CAAC,UAAU,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,IAAI,GAAG,IAAI;IAMpE,SAAS,CAAC,cAAc,IAAI,OAAO;IAoBnC,SAAS,CAAC,eAAe,IAAI,OAAO;IAoBpC,SAAS,CAAC,mBAAmB,IAAI,OAAO;IAMxC,SAAS,CAAC,oBAAoB,IAAI,OAAO;IAMzC,SAAS,CAAC,cAAc,IAAI,QAAQ,GAAG,IAAI;IAK3C,SAAS,CAAC,qBAAqB,IAAI,gBAAgB,GAAG,mBAAmB,GAAG,IAAI;yCAlLrE,aAAa;2CAAb,aAAa;CA6LzB"}
|
|
@@ -3,16 +3,8 @@ import { Subject, takeUntil } from 'rxjs';
|
|
|
3
3
|
import { TngPrefix, TngSuffix } from './tng-adornment';
|
|
4
4
|
import { TngInput } from './tng-input';
|
|
5
5
|
import * as i0 from "@angular/core";
|
|
6
|
-
function
|
|
7
|
-
return
|
|
8
|
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
11
|
-
if (node.nodeType === Node.TEXT_NODE) {
|
|
12
|
-
return (node.textContent ?? '').trim().length > 0;
|
|
13
|
-
}
|
|
14
|
-
return false;
|
|
15
|
-
});
|
|
6
|
+
function containsProjectedContent(childElementCount, textContent) {
|
|
7
|
+
return childElementCount > 0 || (textContent ?? '').trim().length > 0;
|
|
16
8
|
}
|
|
17
9
|
export class TngInputGroup {
|
|
18
10
|
hasLeading = input(null, ...(ngDevMode ? [{ debugName: "hasLeading" }] : []));
|
|
@@ -33,10 +25,10 @@ export class TngInputGroup {
|
|
|
33
25
|
if (!this.controls)
|
|
34
26
|
return;
|
|
35
27
|
const queriedCount = this.controls.length;
|
|
36
|
-
const domCount = this.hostElement.querySelectorAll('[data-tng-input-control-proxy] input, [data-tng-input-control-proxy] textarea, input[tngInput], textarea[tngInput]').length;
|
|
28
|
+
const domCount = this.hostElement.querySelectorAll('[data-tng-input-control-proxy] input, [data-tng-input-control-proxy] textarea, input[tngInput], textarea[tngInput], textarea[tngTextarea]').length;
|
|
37
29
|
const count = this.controlCount() ?? (queriedCount > 0 ? queriedCount : domCount);
|
|
38
30
|
if (count !== 1) {
|
|
39
|
-
console.warn(`[tngInputGroup] Expected exactly 1 control (input/textarea with tngInput), but found ${count}.`, this.hostElement);
|
|
31
|
+
globalThis.console.warn(`[tngInputGroup] Expected exactly 1 control (input/textarea with tngInput or textarea with tngTextarea), but found ${count}.`, this.hostElement);
|
|
40
32
|
}
|
|
41
33
|
}
|
|
42
34
|
ngAfterContentInit() {
|
|
@@ -98,25 +90,40 @@ export class TngInputGroup {
|
|
|
98
90
|
onFocusIn() {
|
|
99
91
|
this.focused = true;
|
|
100
92
|
}
|
|
101
|
-
onFocusOut(
|
|
102
|
-
const nextTarget = event.relatedTarget;
|
|
93
|
+
onFocusOut(nextTarget) {
|
|
103
94
|
if (nextTarget instanceof Node && this.hostElement.contains(nextTarget))
|
|
104
95
|
return;
|
|
105
96
|
this.focused = false;
|
|
106
97
|
}
|
|
107
98
|
hasLeadingSlot() {
|
|
108
99
|
const proxy = this.hostElement.querySelector('[data-tng-input-prefix-proxy]');
|
|
109
|
-
if (proxy instanceof HTMLElement
|
|
110
|
-
|
|
100
|
+
if (proxy instanceof HTMLElement &&
|
|
101
|
+
containsProjectedContent(proxy.childElementCount, proxy.textContent)) {
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
111
104
|
const slots = this.prefixSlots?.toArray() ?? [];
|
|
112
|
-
|
|
105
|
+
for (const slot of slots) {
|
|
106
|
+
const hostElement = slot.hostElement;
|
|
107
|
+
if (containsProjectedContent(hostElement.childElementCount, hostElement.textContent)) {
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
113
112
|
}
|
|
114
113
|
hasTrailingSlot() {
|
|
115
114
|
const proxy = this.hostElement.querySelector('[data-tng-input-suffix-proxy]');
|
|
116
|
-
if (proxy instanceof HTMLElement
|
|
117
|
-
|
|
115
|
+
if (proxy instanceof HTMLElement &&
|
|
116
|
+
containsProjectedContent(proxy.childElementCount, proxy.textContent)) {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
118
119
|
const slots = this.suffixSlots?.toArray() ?? [];
|
|
119
|
-
|
|
120
|
+
for (const slot of slots) {
|
|
121
|
+
const hostElement = slot.hostElement;
|
|
122
|
+
if (containsProjectedContent(hostElement.childElementCount, hostElement.textContent)) {
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
120
127
|
}
|
|
121
128
|
effectiveHasLeading() {
|
|
122
129
|
const override = this.hasLeading();
|
|
@@ -135,14 +142,14 @@ export class TngInputGroup {
|
|
|
135
142
|
return controls[0] ?? null;
|
|
136
143
|
}
|
|
137
144
|
primaryControlElement() {
|
|
138
|
-
const element = this.hostElement.querySelector('[data-tng-input-control-proxy] input, [data-tng-input-control-proxy] textarea, input[tngInput], textarea[tngInput]');
|
|
145
|
+
const element = this.hostElement.querySelector('[data-tng-input-control-proxy] input, [data-tng-input-control-proxy] textarea, input[tngInput], textarea[tngInput], textarea[tngTextarea]');
|
|
139
146
|
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
|
|
140
147
|
return element;
|
|
141
148
|
}
|
|
142
149
|
return null;
|
|
143
150
|
}
|
|
144
151
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
145
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: TngInputGroup, isStandalone: true, selector: "tng-input-group, [tngInputGroup]", inputs: { hasLeading: { classPropertyName: "hasLeading", publicName: "hasLeading", isSignal: true, isRequired: false, transformFunction: null }, hasTrailing: { classPropertyName: "hasTrailing", publicName: "hasTrailing", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, controlCount: { classPropertyName: "controlCount", publicName: "controlCount", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "focusin": "onFocusIn()", "focusout": "onFocusOut($event)" }, properties: { "attr.data-slot": "this.dataSlot", "attr.data-has-leading": "this.dataHasLeading", "attr.data-has-trailing": "this.dataHasTrailing", "attr.data-disabled": "this.dataDisabled", "attr.data-invalid": "this.dataInvalid", "attr.data-readonly": "this.dataReadonly", "attr.data-focused": "this.dataFocused" } }, queries: [{ propertyName: "controls", predicate: TngInput, descendants: true }, { propertyName: "prefixSlots", predicate: TngPrefix, descendants: true }, { propertyName: "suffixSlots", predicate: TngSuffix, descendants: true }], exportAs: ["tngInputGroup"], ngImport: i0, template: `
|
|
152
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: TngInputGroup, isStandalone: true, selector: "tng-input-group, [tngInputGroup]", inputs: { hasLeading: { classPropertyName: "hasLeading", publicName: "hasLeading", isSignal: true, isRequired: false, transformFunction: null }, hasTrailing: { classPropertyName: "hasTrailing", publicName: "hasTrailing", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, controlCount: { classPropertyName: "controlCount", publicName: "controlCount", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "focusin": "onFocusIn()", "focusout": "onFocusOut($event.relatedTarget)" }, properties: { "attr.data-slot": "this.dataSlot", "attr.data-has-leading": "this.dataHasLeading", "attr.data-has-trailing": "this.dataHasTrailing", "attr.data-disabled": "this.dataDisabled", "attr.data-invalid": "this.dataInvalid", "attr.data-readonly": "this.dataReadonly", "attr.data-focused": "this.dataFocused" } }, queries: [{ propertyName: "controls", predicate: TngInput, descendants: true }, { propertyName: "prefixSlots", predicate: TngPrefix, descendants: true }, { propertyName: "suffixSlots", predicate: TngSuffix, descendants: true }], exportAs: ["tngInputGroup"], ngImport: i0, template: `
|
|
146
153
|
@if (hasLeadingSlot()) {
|
|
147
154
|
<span class="tng-input-group-leading" data-slot="input-group-leading">
|
|
148
155
|
<ng-content select="[tngPrefix], [tngInputLeading], [data-tng-input-prefix-proxy]"></ng-content>
|
|
@@ -150,7 +157,7 @@ export class TngInputGroup {
|
|
|
150
157
|
}
|
|
151
158
|
|
|
152
159
|
<span class="tng-input-group-control" data-slot="input-group-control">
|
|
153
|
-
<ng-content select="input[tngInput], textarea[tngInput], [data-tng-input-control-proxy]"></ng-content>
|
|
160
|
+
<ng-content select="input[tngInput], textarea[tngInput], textarea[tngTextarea], [data-tng-input-control-proxy]"></ng-content>
|
|
154
161
|
</span>
|
|
155
162
|
|
|
156
163
|
@if (hasTrailingSlot()) {
|
|
@@ -170,7 +177,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
|
|
|
170
177
|
}
|
|
171
178
|
|
|
172
179
|
<span class="tng-input-group-control" data-slot="input-group-control">
|
|
173
|
-
<ng-content select="input[tngInput], textarea[tngInput], [data-tng-input-control-proxy]"></ng-content>
|
|
180
|
+
<ng-content select="input[tngInput], textarea[tngInput], textarea[tngTextarea], [data-tng-input-control-proxy]"></ng-content>
|
|
174
181
|
</span>
|
|
175
182
|
|
|
176
183
|
@if (hasTrailingSlot()) {
|
|
@@ -214,6 +221,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
|
|
|
214
221
|
args: ['focusin']
|
|
215
222
|
}], onFocusOut: [{
|
|
216
223
|
type: HostListener,
|
|
217
|
-
args: ['focusout', ['$event']]
|
|
224
|
+
args: ['focusout', ['$event.relatedTarget']]
|
|
218
225
|
}] } });
|
|
219
226
|
//# sourceMappingURL=tng-input-group.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tng-input-group.js","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input/tng-input-group.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AfterContentInit, OnDestroy, QueryList } from '@angular/core';\nimport {\n Component,\n ContentChildren,\n ElementRef,\n HostBinding,\n HostListener,\n inject,\n input,\n isDevMode,\n} from '@angular/core';\nimport { Subject, takeUntil } from 'rxjs';\n\nimport { TngPrefix, TngSuffix } from './tng-adornment';\nimport { TngInput } from './tng-input';\n\nfunction hasProjectedContent(element: HTMLElement): boolean {\n return Array.from(element.childNodes).some((node) => {\n if (node.nodeType === Node.ELEMENT_NODE) {\n return true;\n }\n\n if (node.nodeType === Node.TEXT_NODE) {\n return (node.textContent ?? '').trim().length > 0;\n }\n\n return false;\n });\n}\n\n@Component({\n selector: 'tng-input-group, [tngInputGroup]',\n exportAs: 'tngInputGroup',\n template: `\n @if (hasLeadingSlot()) {\n <span class=\"tng-input-group-leading\" data-slot=\"input-group-leading\">\n <ng-content select=\"[tngPrefix], [tngInputLeading], [data-tng-input-prefix-proxy]\"></ng-content>\n </span>\n }\n\n <span class=\"tng-input-group-control\" data-slot=\"input-group-control\">\n <ng-content select=\"input[tngInput], textarea[tngInput], [data-tng-input-control-proxy]\"></ng-content>\n </span>\n\n @if (hasTrailingSlot()) {\n <span class=\"tng-input-group-trailing\" data-slot=\"input-group-trailing\">\n <ng-content select=\"[tngSuffix], [tngInputTrailing], [data-tng-input-suffix-proxy]\"></ng-content>\n </span>\n }\n `,\n styles: [\n `\n :host {\n display: flex;\n align-items: center;\n min-width: 0;\n }\n\n .tng-input-group-leading,\n .tng-input-group-trailing {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n min-width: 0;\n }\n\n .tng-input-group-control {\n flex: 1 1 auto;\n display: flex;\n align-items: center;\n min-width: 0;\n }\n `,\n ],\n})\nexport class TngInputGroup implements AfterContentInit, OnDestroy {\n public readonly hasLeading = input<boolean | null>(null);\n public readonly hasTrailing = input<boolean | null>(null);\n public readonly disabled = input<boolean | null>(null);\n public readonly invalid = input<boolean | null>(null);\n public readonly readonly = input<boolean | null>(null);\n public readonly controlCount = input<number | null>(null);\n\n @ContentChildren(TngInput, { descendants: true })\n protected controls!: QueryList<TngInput>;\n\n @ContentChildren(TngPrefix, { descendants: true })\n protected prefixSlots!: QueryList<TngPrefix>;\n\n @ContentChildren(TngSuffix, { descendants: true })\n protected suffixSlots!: QueryList<TngSuffix>;\n\n private readonly hostElement = inject(ElementRef<HTMLElement>).nativeElement;\n private focused = false;\n private readonly destroyed$ = new Subject<void>();\n\n private validateSingleControl(): void {\n if (!isDevMode()) return;\n if (!this.controls) return;\n\n const queriedCount = this.controls.length;\n const domCount = this.hostElement.querySelectorAll(\n '[data-tng-input-control-proxy] input, [data-tng-input-control-proxy] textarea, input[tngInput], textarea[tngInput]',\n ).length;\n\n const count = this.controlCount() ?? (queriedCount > 0 ? queriedCount : domCount);\n\n if (count !== 1) {\n console.warn(\n `[tngInputGroup] Expected exactly 1 control (input/textarea with tngInput), but found ${count}.`,\n this.hostElement,\n );\n }\n }\n\n public ngAfterContentInit(): void {\n queueMicrotask(() => this.validateSingleControl());\n\n this.controls.changes.pipe(takeUntil(this.destroyed$)).subscribe(() => this.validateSingleControl());\n }\n\n public ngOnDestroy(): void {\n this.destroyed$.next();\n this.destroyed$.complete();\n }\n\n @HostBinding('attr.data-slot')\n protected readonly dataSlot = 'input-group' as const;\n\n @HostBinding('attr.data-has-leading')\n protected get dataHasLeading(): '' | null {\n return this.effectiveHasLeading() ? '' : null;\n }\n\n @HostBinding('attr.data-has-trailing')\n protected get dataHasTrailing(): '' | null {\n return this.effectiveHasTrailing() ? '' : null;\n }\n\n @HostBinding('attr.data-disabled')\n protected get dataDisabled(): '' | null {\n const override = this.disabled();\n if (override !== null) return override ? '' : null;\n\n const control = this.primaryControl();\n if (control !== null) return control.disabled() ? '' : null;\n\n const element = this.primaryControlElement();\n if (element === null) return null;\n return element.hasAttribute('disabled') ? '' : null;\n }\n\n @HostBinding('attr.data-invalid')\n protected get dataInvalid(): '' | null {\n const override = this.invalid();\n if (override !== null) return override ? '' : null;\n\n const control = this.primaryControl();\n if (control !== null) return control.isInvalid() ? '' : null;\n\n const element = this.primaryControlElement();\n if (element === null) return null;\n if (element.getAttribute('aria-invalid') === 'true') return '';\n return element.matches(':invalid') ? '' : null;\n }\n\n @HostBinding('attr.data-readonly')\n protected get dataReadonly(): '' | null {\n const override = this.readonly();\n if (override !== null) return override ? '' : null;\n\n const control = this.primaryControl();\n if (control !== null) return control.readonly() ? '' : null;\n\n const element = this.primaryControlElement();\n if (element === null) return null;\n return element.hasAttribute('readonly') ? '' : null;\n }\n\n @HostBinding('attr.data-focused')\n protected get dataFocused(): '' | null {\n return this.focused ? '' : null;\n }\n\n @HostListener('focusin')\n protected onFocusIn(): void {\n this.focused = true;\n }\n\n @HostListener('focusout', ['$event'])\n protected onFocusOut(event: FocusEvent): void {\n const nextTarget = event.relatedTarget;\n if (nextTarget instanceof Node && this.hostElement.contains(nextTarget)) return;\n\n this.focused = false;\n }\n\n protected hasLeadingSlot(): boolean {\n const proxy = this.hostElement.querySelector('[data-tng-input-prefix-proxy]');\n if (proxy instanceof HTMLElement) return hasProjectedContent(proxy);\n\n const slots = this.prefixSlots?.toArray() ?? [];\n return slots.some((slot) => hasProjectedContent(slot.hostElement));\n }\n\n protected hasTrailingSlot(): boolean {\n const proxy = this.hostElement.querySelector('[data-tng-input-suffix-proxy]');\n if (proxy instanceof HTMLElement) return hasProjectedContent(proxy);\n\n const slots = this.suffixSlots?.toArray() ?? [];\n return slots.some((slot) => hasProjectedContent(slot.hostElement));\n }\n\n protected effectiveHasLeading(): boolean {\n const override = this.hasLeading();\n if (override !== null) return override;\n return this.hasLeadingSlot();\n }\n\n protected effectiveHasTrailing(): boolean {\n const override = this.hasTrailing();\n if (override !== null) return override;\n return this.hasTrailingSlot();\n }\n\n protected primaryControl(): TngInput | null {\n const controls = this.controls?.toArray() ?? [];\n return controls[0] ?? null;\n }\n\n protected primaryControlElement(): HTMLInputElement | HTMLTextAreaElement | null {\n const element = this.hostElement.querySelector(\n '[data-tng-input-control-proxy] input, [data-tng-input-control-proxy] textarea, input[tngInput], textarea[tngInput]',\n );\n\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n return element;\n }\n\n return null;\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"tng-input-group.js","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input/tng-input-group.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AfterContentInit, OnDestroy, QueryList } from '@angular/core';\nimport {\n Component,\n ContentChildren,\n ElementRef,\n HostBinding,\n HostListener,\n inject,\n input,\n isDevMode,\n} from '@angular/core';\nimport { Subject, takeUntil } from 'rxjs';\n\nimport { TngPrefix, TngSuffix } from './tng-adornment';\nimport { TngInput } from './tng-input';\n\nfunction containsProjectedContent(childElementCount: number, textContent: string | null): boolean {\n return childElementCount > 0 || (textContent ?? '').trim().length > 0;\n}\n\n@Component({\n selector: 'tng-input-group, [tngInputGroup]',\n exportAs: 'tngInputGroup',\n template: `\n @if (hasLeadingSlot()) {\n <span class=\"tng-input-group-leading\" data-slot=\"input-group-leading\">\n <ng-content select=\"[tngPrefix], [tngInputLeading], [data-tng-input-prefix-proxy]\"></ng-content>\n </span>\n }\n\n <span class=\"tng-input-group-control\" data-slot=\"input-group-control\">\n <ng-content select=\"input[tngInput], textarea[tngInput], textarea[tngTextarea], [data-tng-input-control-proxy]\"></ng-content>\n </span>\n\n @if (hasTrailingSlot()) {\n <span class=\"tng-input-group-trailing\" data-slot=\"input-group-trailing\">\n <ng-content select=\"[tngSuffix], [tngInputTrailing], [data-tng-input-suffix-proxy]\"></ng-content>\n </span>\n }\n `,\n styles: [\n `\n :host {\n display: flex;\n align-items: center;\n min-width: 0;\n }\n\n .tng-input-group-leading,\n .tng-input-group-trailing {\n flex: 0 0 auto;\n display: inline-flex;\n align-items: center;\n min-width: 0;\n }\n\n .tng-input-group-control {\n flex: 1 1 auto;\n display: flex;\n align-items: center;\n min-width: 0;\n }\n `,\n ],\n})\nexport class TngInputGroup implements AfterContentInit, OnDestroy {\n public readonly hasLeading = input<boolean | null>(null);\n public readonly hasTrailing = input<boolean | null>(null);\n public readonly disabled = input<boolean | null>(null);\n public readonly invalid = input<boolean | null>(null);\n public readonly readonly = input<boolean | null>(null);\n public readonly controlCount = input<number | null>(null);\n\n @ContentChildren(TngInput, { descendants: true })\n protected controls!: QueryList<TngInput>;\n\n @ContentChildren(TngPrefix, { descendants: true })\n protected prefixSlots!: QueryList<TngPrefix>;\n\n @ContentChildren(TngSuffix, { descendants: true })\n protected suffixSlots!: QueryList<TngSuffix>;\n\n private readonly hostElement: HTMLElement = inject(ElementRef<HTMLElement>).nativeElement as HTMLElement;\n private focused = false;\n private readonly destroyed$ = new Subject<void>();\n\n private validateSingleControl(): void {\n if (!isDevMode()) return;\n if (!this.controls) return;\n\n const queriedCount = this.controls.length;\n const domCount = this.hostElement.querySelectorAll(\n '[data-tng-input-control-proxy] input, [data-tng-input-control-proxy] textarea, input[tngInput], textarea[tngInput], textarea[tngTextarea]',\n ).length;\n\n const count = this.controlCount() ?? (queriedCount > 0 ? queriedCount : domCount);\n\n if (count !== 1) {\n globalThis.console.warn(\n `[tngInputGroup] Expected exactly 1 control (input/textarea with tngInput or textarea with tngTextarea), but found ${count}.`,\n this.hostElement,\n );\n }\n }\n\n public ngAfterContentInit(): void {\n queueMicrotask(() => this.validateSingleControl());\n\n this.controls.changes.pipe(takeUntil(this.destroyed$)).subscribe(() => this.validateSingleControl());\n }\n\n public ngOnDestroy(): void {\n this.destroyed$.next();\n this.destroyed$.complete();\n }\n\n @HostBinding('attr.data-slot')\n protected readonly dataSlot = 'input-group' as const;\n\n @HostBinding('attr.data-has-leading')\n protected get dataHasLeading(): '' | null {\n return this.effectiveHasLeading() ? '' : null;\n }\n\n @HostBinding('attr.data-has-trailing')\n protected get dataHasTrailing(): '' | null {\n return this.effectiveHasTrailing() ? '' : null;\n }\n\n @HostBinding('attr.data-disabled')\n protected get dataDisabled(): '' | null {\n const override = this.disabled();\n if (override !== null) return override ? '' : null;\n\n const control = this.primaryControl();\n if (control !== null) return control.disabled() ? '' : null;\n\n const element = this.primaryControlElement();\n if (element === null) return null;\n return element.hasAttribute('disabled') ? '' : null;\n }\n\n @HostBinding('attr.data-invalid')\n protected get dataInvalid(): '' | null {\n const override = this.invalid();\n if (override !== null) return override ? '' : null;\n\n const control = this.primaryControl();\n if (control !== null) return control.isInvalid() ? '' : null;\n\n const element = this.primaryControlElement();\n if (element === null) return null;\n if (element.getAttribute('aria-invalid') === 'true') return '';\n return element.matches(':invalid') ? '' : null;\n }\n\n @HostBinding('attr.data-readonly')\n protected get dataReadonly(): '' | null {\n const override = this.readonly();\n if (override !== null) return override ? '' : null;\n\n const control = this.primaryControl();\n if (control !== null) return control.readonly() ? '' : null;\n\n const element = this.primaryControlElement();\n if (element === null) return null;\n return element.hasAttribute('readonly') ? '' : null;\n }\n\n @HostBinding('attr.data-focused')\n protected get dataFocused(): '' | null {\n return this.focused ? '' : null;\n }\n\n @HostListener('focusin')\n protected onFocusIn(): void {\n this.focused = true;\n }\n\n @HostListener('focusout', ['$event.relatedTarget'])\n protected onFocusOut(nextTarget: Readonly<EventTarget> | null): void {\n if (nextTarget instanceof Node && this.hostElement.contains(nextTarget)) return;\n\n this.focused = false;\n }\n\n protected hasLeadingSlot(): boolean {\n const proxy = this.hostElement.querySelector('[data-tng-input-prefix-proxy]');\n if (\n proxy instanceof HTMLElement &&\n containsProjectedContent(proxy.childElementCount, proxy.textContent)\n ) {\n return true;\n }\n\n const slots = this.prefixSlots?.toArray() ?? [];\n for (const slot of slots) {\n const hostElement = slot.hostElement;\n if (containsProjectedContent(hostElement.childElementCount, hostElement.textContent)) {\n return true;\n }\n }\n\n return false;\n }\n\n protected hasTrailingSlot(): boolean {\n const proxy = this.hostElement.querySelector('[data-tng-input-suffix-proxy]');\n if (\n proxy instanceof HTMLElement &&\n containsProjectedContent(proxy.childElementCount, proxy.textContent)\n ) {\n return true;\n }\n\n const slots = this.suffixSlots?.toArray() ?? [];\n for (const slot of slots) {\n const hostElement = slot.hostElement;\n if (containsProjectedContent(hostElement.childElementCount, hostElement.textContent)) {\n return true;\n }\n }\n\n return false;\n }\n\n protected effectiveHasLeading(): boolean {\n const override = this.hasLeading();\n if (override !== null) return override;\n return this.hasLeadingSlot();\n }\n\n protected effectiveHasTrailing(): boolean {\n const override = this.hasTrailing();\n if (override !== null) return override;\n return this.hasTrailingSlot();\n }\n\n protected primaryControl(): TngInput | null {\n const controls = this.controls?.toArray() ?? [];\n return controls[0] ?? null;\n }\n\n protected primaryControlElement(): HTMLInputElement | HTMLTextAreaElement | null {\n const element = this.hostElement.querySelector(\n '[data-tng-input-control-proxy] input, [data-tng-input-control-proxy] textarea, input[tngInput], textarea[tngInput], textarea[tngTextarea]',\n );\n\n if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {\n return element;\n }\n\n return null;\n }\n}\n"]}
|