@tailng-ui/primitives 0.15.0 → 0.18.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.
Files changed (57) hide show
  1. package/package.json +2 -2
  2. package/src/index.d.ts +6 -60
  3. package/src/index.d.ts.map +1 -1
  4. package/src/index.js +6 -66
  5. package/src/index.js.map +1 -1
  6. package/src/lib/feedback/index.d.ts +6 -0
  7. package/src/lib/feedback/index.d.ts.map +1 -0
  8. package/src/lib/feedback/index.js +7 -0
  9. package/src/lib/feedback/index.js.map +1 -0
  10. package/src/lib/form/autocomplete/tng-autocomplete.listbox.d.ts +3 -2
  11. package/src/lib/form/autocomplete/tng-autocomplete.listbox.d.ts.map +1 -1
  12. package/src/lib/form/autocomplete/tng-autocomplete.listbox.js +6 -3
  13. package/src/lib/form/autocomplete/tng-autocomplete.listbox.js.map +1 -1
  14. package/src/lib/form/index.d.ts +29 -0
  15. package/src/lib/form/index.d.ts.map +1 -0
  16. package/src/lib/form/index.js +33 -0
  17. package/src/lib/form/index.js.map +1 -0
  18. package/src/lib/form/input/tng-adornment.d.ts +14 -0
  19. package/src/lib/form/input/tng-adornment.d.ts.map +1 -0
  20. package/src/lib/form/input/tng-adornment.js +35 -0
  21. package/src/lib/form/input/tng-adornment.js.map +1 -0
  22. package/src/lib/form/input/tng-input-group.d.ts +40 -0
  23. package/src/lib/form/input/tng-input-group.d.ts.map +1 -0
  24. package/src/lib/form/input/tng-input-group.js +229 -0
  25. package/src/lib/form/input/tng-input-group.js.map +1 -0
  26. package/src/lib/form/input/tng-input.d.ts +0 -47
  27. package/src/lib/form/input/tng-input.d.ts.map +1 -1
  28. package/src/lib/form/input/tng-input.js +1 -255
  29. package/src/lib/form/input/tng-input.js.map +1 -1
  30. package/src/lib/form/multi-autocomplete/tng-multi-autocomplete.listbox.d.ts +3 -2
  31. package/src/lib/form/multi-autocomplete/tng-multi-autocomplete.listbox.d.ts.map +1 -1
  32. package/src/lib/form/multi-autocomplete/tng-multi-autocomplete.listbox.js +6 -3
  33. package/src/lib/form/multi-autocomplete/tng-multi-autocomplete.listbox.js.map +1 -1
  34. package/src/lib/form/multi-select/tng-multi-select.listbox.d.ts +3 -2
  35. package/src/lib/form/multi-select/tng-multi-select.listbox.d.ts.map +1 -1
  36. package/src/lib/form/multi-select/tng-multi-select.listbox.js +5 -3
  37. package/src/lib/form/multi-select/tng-multi-select.listbox.js.map +1 -1
  38. package/src/lib/form/select/tng-select.listbox.d.ts +3 -2
  39. package/src/lib/form/select/tng-select.listbox.d.ts.map +1 -1
  40. package/src/lib/form/select/tng-select.listbox.js +5 -3
  41. package/src/lib/form/select/tng-select.listbox.js.map +1 -1
  42. package/src/lib/layout/index.d.ts +13 -0
  43. package/src/lib/layout/index.d.ts.map +1 -0
  44. package/src/lib/layout/index.js +14 -0
  45. package/src/lib/layout/index.js.map +1 -0
  46. package/src/lib/navigation/index.d.ts +9 -0
  47. package/src/lib/navigation/index.d.ts.map +1 -0
  48. package/src/lib/navigation/index.js +10 -0
  49. package/src/lib/navigation/index.js.map +1 -0
  50. package/src/lib/overlay/index.d.ts +4 -0
  51. package/src/lib/overlay/index.d.ts.map +1 -0
  52. package/src/lib/overlay/index.js +5 -0
  53. package/src/lib/overlay/index.js.map +1 -0
  54. package/src/lib/utility/index.d.ts +7 -0
  55. package/src/lib/utility/index.d.ts.map +1 -0
  56. package/src/lib/utility/index.js +8 -0
  57. package/src/lib/utility/index.js.map +1 -0
@@ -0,0 +1,229 @@
1
+ import { Component, ContentChildren, ElementRef, HostBinding, HostListener, inject } from "@angular/core";
2
+ import { isDevMode } from "@angular/core";
3
+ import { input } from "@angular/core";
4
+ import { Subject, takeUntil } from "rxjs";
5
+ import { TngPrefix } from "./tng-adornment";
6
+ import { TngSuffix } from "./tng-adornment";
7
+ import { TngInput } from "./tng-input";
8
+ import * as i0 from "@angular/core";
9
+ function hasProjectedContent(element) {
10
+ return Array.from(element.childNodes).some((node) => {
11
+ if (node.nodeType === Node.ELEMENT_NODE) {
12
+ return true;
13
+ }
14
+ if (node.nodeType === Node.TEXT_NODE) {
15
+ return (node.textContent ?? '').trim().length > 0;
16
+ }
17
+ return false;
18
+ });
19
+ }
20
+ export class TngInputGroup {
21
+ hasLeading = input(null, ...(ngDevMode ? [{ debugName: "hasLeading" }] : []));
22
+ hasTrailing = input(null, ...(ngDevMode ? [{ debugName: "hasTrailing" }] : []));
23
+ disabled = input(null, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
24
+ invalid = input(null, ...(ngDevMode ? [{ debugName: "invalid" }] : []));
25
+ readonly = input(null, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
26
+ controlCount = input(null, ...(ngDevMode ? [{ debugName: "controlCount" }] : []));
27
+ controls;
28
+ prefixSlots;
29
+ suffixSlots;
30
+ hostElement = inject((ElementRef)).nativeElement;
31
+ focused = false;
32
+ destroyed$ = new Subject();
33
+ validateSingleControl() {
34
+ if (!isDevMode())
35
+ return;
36
+ if (!this.controls)
37
+ return;
38
+ const queriedCount = this.controls.length;
39
+ const domCount = this.hostElement.querySelectorAll('[data-tng-input-control-proxy] input, [data-tng-input-control-proxy] textarea, input[tngInput], textarea[tngInput]').length;
40
+ const count = this.controlCount() ?? (queriedCount > 0 ? queriedCount : domCount);
41
+ if (count !== 1) {
42
+ console.warn(`[tngInputGroup] Expected exactly 1 control (input/textarea with tngInput), but found ${count}.`, this.hostElement);
43
+ }
44
+ }
45
+ ngAfterContentInit() {
46
+ queueMicrotask(() => this.validateSingleControl());
47
+ this.controls.changes
48
+ .pipe(takeUntil(this.destroyed$))
49
+ .subscribe(() => this.validateSingleControl());
50
+ }
51
+ ngOnDestroy() {
52
+ this.destroyed$.next();
53
+ this.destroyed$.complete();
54
+ }
55
+ dataSlot = 'input-group';
56
+ get dataHasLeading() {
57
+ return this.effectiveHasLeading() ? '' : null;
58
+ }
59
+ get dataHasTrailing() {
60
+ return this.effectiveHasTrailing() ? '' : null;
61
+ }
62
+ get dataDisabled() {
63
+ const override = this.disabled();
64
+ if (override !== null)
65
+ return override ? '' : null;
66
+ const control = this.primaryControl();
67
+ if (control !== null)
68
+ return control.disabled() ? '' : null;
69
+ const element = this.primaryControlElement();
70
+ if (element === null)
71
+ return null;
72
+ return element.hasAttribute('disabled') ? '' : null;
73
+ }
74
+ get dataInvalid() {
75
+ const override = this.invalid();
76
+ if (override !== null)
77
+ return override ? '' : null;
78
+ const control = this.primaryControl();
79
+ if (control !== null)
80
+ return control.isInvalid() ? '' : null;
81
+ const element = this.primaryControlElement();
82
+ if (element === null)
83
+ return null;
84
+ if (element.getAttribute('aria-invalid') === 'true')
85
+ return '';
86
+ return element.matches(':invalid') ? '' : null;
87
+ }
88
+ get dataReadonly() {
89
+ const override = this.readonly();
90
+ if (override !== null)
91
+ return override ? '' : null;
92
+ const control = this.primaryControl();
93
+ if (control !== null)
94
+ return control.readonly() ? '' : null;
95
+ const element = this.primaryControlElement();
96
+ if (element === null)
97
+ return null;
98
+ return element.hasAttribute('readonly') ? '' : null;
99
+ }
100
+ get dataFocused() {
101
+ return this.focused ? '' : null;
102
+ }
103
+ onFocusIn() {
104
+ this.focused = true;
105
+ }
106
+ onFocusOut(event) {
107
+ const nextTarget = event.relatedTarget;
108
+ if (nextTarget instanceof Node && this.hostElement.contains(nextTarget))
109
+ return;
110
+ this.focused = false;
111
+ }
112
+ hasLeadingSlot() {
113
+ const proxy = this.hostElement.querySelector('[data-tng-input-prefix-proxy]');
114
+ if (proxy instanceof HTMLElement)
115
+ return hasProjectedContent(proxy);
116
+ const slots = this.prefixSlots?.toArray() ?? [];
117
+ return slots.some((slot) => hasProjectedContent(slot.hostElement));
118
+ }
119
+ hasTrailingSlot() {
120
+ const proxy = this.hostElement.querySelector('[data-tng-input-suffix-proxy]');
121
+ if (proxy instanceof HTMLElement)
122
+ return hasProjectedContent(proxy);
123
+ const slots = this.suffixSlots?.toArray() ?? [];
124
+ return slots.some((slot) => hasProjectedContent(slot.hostElement));
125
+ }
126
+ effectiveHasLeading() {
127
+ const override = this.hasLeading();
128
+ if (override !== null)
129
+ return override;
130
+ return this.hasLeadingSlot();
131
+ }
132
+ effectiveHasTrailing() {
133
+ const override = this.hasTrailing();
134
+ if (override !== null)
135
+ return override;
136
+ return this.hasTrailingSlot();
137
+ }
138
+ primaryControl() {
139
+ const controls = this.controls?.toArray() ?? [];
140
+ return controls[0] ?? null;
141
+ }
142
+ primaryControlElement() {
143
+ const element = this.hostElement.querySelector('[data-tng-input-control-proxy] input, [data-tng-input-control-proxy] textarea, input[tngInput], textarea[tngInput]');
144
+ if (element instanceof HTMLInputElement ||
145
+ element instanceof HTMLTextAreaElement) {
146
+ return element;
147
+ }
148
+ return null;
149
+ }
150
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
151
+ 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
+ @if (hasLeadingSlot()) {
153
+ <span class="tng-input-group-leading" data-slot="input-group-leading">
154
+ <ng-content select="[tngPrefix], [tngInputLeading], [data-tng-input-prefix-proxy]"></ng-content>
155
+ </span>
156
+ }
157
+
158
+ <span class="tng-input-group-control" data-slot="input-group-control">
159
+ <ng-content select="input[tngInput], textarea[tngInput], [data-tng-input-control-proxy]"></ng-content>
160
+ </span>
161
+
162
+ @if (hasTrailingSlot()) {
163
+ <span class="tng-input-group-trailing" data-slot="input-group-trailing">
164
+ <ng-content select="[tngSuffix], [tngInputTrailing], [data-tng-input-suffix-proxy]"></ng-content>
165
+ </span>
166
+ }
167
+ `, isInline: true });
168
+ }
169
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputGroup, decorators: [{
170
+ type: Component,
171
+ args: [{
172
+ selector: 'tng-input-group, [tngInputGroup]',
173
+ exportAs: 'tngInputGroup',
174
+ template: `
175
+ @if (hasLeadingSlot()) {
176
+ <span class="tng-input-group-leading" data-slot="input-group-leading">
177
+ <ng-content select="[tngPrefix], [tngInputLeading], [data-tng-input-prefix-proxy]"></ng-content>
178
+ </span>
179
+ }
180
+
181
+ <span class="tng-input-group-control" data-slot="input-group-control">
182
+ <ng-content select="input[tngInput], textarea[tngInput], [data-tng-input-control-proxy]"></ng-content>
183
+ </span>
184
+
185
+ @if (hasTrailingSlot()) {
186
+ <span class="tng-input-group-trailing" data-slot="input-group-trailing">
187
+ <ng-content select="[tngSuffix], [tngInputTrailing], [data-tng-input-suffix-proxy]"></ng-content>
188
+ </span>
189
+ }
190
+ `,
191
+ }]
192
+ }], propDecorators: { hasLeading: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasLeading", required: false }] }], hasTrailing: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasTrailing", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], controlCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlCount", required: false }] }], controls: [{
193
+ type: ContentChildren,
194
+ args: [TngInput, { descendants: true }]
195
+ }], prefixSlots: [{
196
+ type: ContentChildren,
197
+ args: [TngPrefix, { descendants: true }]
198
+ }], suffixSlots: [{
199
+ type: ContentChildren,
200
+ args: [TngSuffix, { descendants: true }]
201
+ }], dataSlot: [{
202
+ type: HostBinding,
203
+ args: ['attr.data-slot']
204
+ }], dataHasLeading: [{
205
+ type: HostBinding,
206
+ args: ['attr.data-has-leading']
207
+ }], dataHasTrailing: [{
208
+ type: HostBinding,
209
+ args: ['attr.data-has-trailing']
210
+ }], dataDisabled: [{
211
+ type: HostBinding,
212
+ args: ['attr.data-disabled']
213
+ }], dataInvalid: [{
214
+ type: HostBinding,
215
+ args: ['attr.data-invalid']
216
+ }], dataReadonly: [{
217
+ type: HostBinding,
218
+ args: ['attr.data-readonly']
219
+ }], dataFocused: [{
220
+ type: HostBinding,
221
+ args: ['attr.data-focused']
222
+ }], onFocusIn: [{
223
+ type: HostListener,
224
+ args: ['focusin']
225
+ }], onFocusOut: [{
226
+ type: HostListener,
227
+ args: ['focusout', ['$event']]
228
+ }] } });
229
+ //# sourceMappingURL=tng-input-group.js.map
@@ -0,0 +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 { OnDestroy, AfterContentInit, QueryList } from \"@angular/core\";\nimport { Component, ContentChildren, ElementRef, HostBinding, HostListener, inject } from \"@angular/core\";\nimport { isDevMode } from \"@angular/core\";\nimport { input } from \"@angular/core\";\nimport { Subject, takeUntil } from \"rxjs\";\nimport { TngPrefix } from \"./tng-adornment\";\nimport { 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})\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\n private focused = false;\n\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 const count = this.controlCount() ?? (queriedCount > 0 ? queriedCount : domCount);\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\n .pipe(takeUntil(this.destroyed$))\n .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 if (\n element instanceof HTMLInputElement ||\n element instanceof HTMLTextAreaElement\n ) {\n return element;\n }\n\n return null;\n }\n}"]}
@@ -1,4 +1,3 @@
1
- import { AfterContentInit, OnDestroy, QueryList } from '@angular/core';
2
1
  import * as i0 from "@angular/core";
3
2
  type NullableBooleanInput = boolean | null | string | undefined;
4
3
  export type TngInputType = 'email' | 'number' | 'password' | 'search' | 'tel' | 'text' | 'url';
@@ -46,51 +45,5 @@ export declare class TngInput {
46
45
  static ɵfac: i0.ɵɵFactoryDeclaration<TngInput, never>;
47
46
  static ɵdir: i0.ɵɵDirectiveDeclaration<TngInput, "input[tngInput], textarea[tngInput]", ["tngInput"], { "ariaDescribedBy": { "alias": "ariaDescribedBy"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; "ariaLabelledby": { "alias": "ariaLabelledby"; "required": false; "isSignal": true; }; "ariaInvalid": { "alias": "ariaInvalid"; "required": false; "isSignal": true; }; "ariaRequired": { "alias": "ariaRequired"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "required": { "alias": "required"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
48
47
  }
49
- export declare class TngInputLeading {
50
- readonly hostElement: any;
51
- protected readonly dataSlot: "input-leading";
52
- static ɵfac: i0.ɵɵFactoryDeclaration<TngInputLeading, never>;
53
- static ɵdir: i0.ɵɵDirectiveDeclaration<TngInputLeading, "[tngInputLeading]", ["tngInputLeading"], {}, {}, never, never, true, never>;
54
- }
55
- export declare class TngInputTrailing {
56
- readonly hostElement: any;
57
- protected readonly dataSlot: "input-trailing";
58
- static ɵfac: i0.ɵɵFactoryDeclaration<TngInputTrailing, never>;
59
- static ɵdir: i0.ɵɵDirectiveDeclaration<TngInputTrailing, "[tngInputTrailing]", ["tngInputTrailing"], {}, {}, never, never, true, never>;
60
- }
61
- export declare class TngInputGroup implements AfterContentInit, OnDestroy {
62
- readonly hasLeading: import("@angular/core").InputSignal<boolean | null>;
63
- readonly hasTrailing: import("@angular/core").InputSignal<boolean | null>;
64
- readonly disabled: import("@angular/core").InputSignal<boolean | null>;
65
- readonly invalid: import("@angular/core").InputSignal<boolean | null>;
66
- readonly readonly: import("@angular/core").InputSignal<boolean | null>;
67
- readonly controlCount: import("@angular/core").InputSignal<number | null>;
68
- protected controls: QueryList<TngInput>;
69
- protected leadingSlots: QueryList<TngInputLeading>;
70
- protected trailingSlots: QueryList<TngInputTrailing>;
71
- private readonly hostElement;
72
- private focused;
73
- private readonly destroyed$;
74
- private validateSingleControl;
75
- ngAfterContentInit(): void;
76
- ngOnDestroy(): void;
77
- protected readonly dataSlot: "input-group";
78
- protected get dataHasLeading(): '' | null;
79
- protected get dataHasTrailing(): '' | null;
80
- protected get dataDisabled(): '' | null;
81
- protected get dataInvalid(): '' | null;
82
- protected get dataReadonly(): '' | null;
83
- protected get dataFocused(): '' | null;
84
- protected onFocusIn(): void;
85
- protected onFocusOut(event: FocusEvent): void;
86
- protected hasLeadingSlot(): boolean;
87
- protected hasTrailingSlot(): boolean;
88
- protected effectiveHasLeading(): boolean;
89
- protected effectiveHasTrailing(): boolean;
90
- protected primaryControl(): TngInput | null;
91
- protected primaryControlElement(): HTMLInputElement | HTMLTextAreaElement | null;
92
- static ɵfac: i0.ɵɵFactoryDeclaration<TngInputGroup, never>;
93
- 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", "leadingSlots", "trailingSlots"], ["[tngInputLeading], [data-tng-input-leading-proxy]", "input[tngInput], textarea[tngInput], [data-tng-input-control-proxy]", "[tngInputTrailing], [data-tng-input-trailing-proxy]"], true, never>;
94
- }
95
48
  export {};
96
49
  //# sourceMappingURL=tng-input.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tng-input.d.ts","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input/tng-input.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tng-input.d.ts","sourceRoot":"","sources":["../../../../../../../../libs/tailng-ui/primitives/src/lib/form/input/tng-input.ts"],"names":[],"mappings":";AAWA,KAAK,oBAAoB,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;AAEhE,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;AAE/F,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,oBAAoB,GAAG,OAAO,GAAG,IAAI,CAQzF;AAcD,qBAIa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA8D;IACzF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA8B;IAExD,SAAgB,WAAW,MAAiC;IAC5D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqE;IACtG,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAA0E;IAChH,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAErC;IAEF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAsC;IAElE,kEAAkE;IAClE,SAAgB,eAAe,qDAA8B;IAE7D,SAAgB,SAAS,qDAA8B;IACvD,SAAgB,cAAc,qDAA8B;IAE5D,0EAA0E;IAC1E,SAAgB,WAAW,yFAExB;IAEH,SAAgB,YAAY,yFAEzB;IAEH,SAAgB,QAAQ,8EAA4E;IACpG,SAAgB,QAAQ,8EAA4E;IACpG,SAAgB,QAAQ,8EAA4E;IAGpG,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAG,OAAO,CAAU;IAG/C,SAAS,KAAK,MAAM,IAAI,MAAM,CAG7B;IAGD,SAAS,KAAK,aAAa,IAAI,MAAM,GAAG,IAAI,CAK3C;IAGD,SAAS,KAAK,kBAAkB,IAAI,MAAM,GAAG,IAAI,CAKhD;IAED;;;OAGG;IAEH,SAAS,KAAK,mBAAmB,IAAI,MAAM,GAAG,IAAI,CAKjD;IAED;;;OAGG;IAEH,SAAS,KAAK,eAAe,IAAI,MAAM,GAAG,IAAI,CAE7C;IAGD,SAAS,KAAK,gBAAgB,IAAI,OAAO,GAAG,MAAM,GAAG,IAAI,CAGxD;IAGD,SAAS,KAAK,gBAAgB,IAAI,EAAE,GAAG,IAAI,CAE1C;IAGD,SAAS,KAAK,eAAe,IAAI,EAAE,GAAG,IAAI,CAEzC;IAGD,SAAS,KAAK,gBAAgB,IAAI,EAAE,GAAG,IAAI,CAE1C;IAGD,SAAS,KAAK,YAAY,IAAI,EAAE,GAAG,IAAI,CAEtC;IAGD,SAAS,KAAK,YAAY,IAAI,EAAE,GAAG,IAAI,CAEtC;IAGD,SAAS,KAAK,YAAY,IAAI,EAAE,GAAG,IAAI,CAEtC;IAEM,SAAS,IAAI,OAAO;yCAlHhB,QAAQ;2CAAR,QAAQ;CAyHpB"}
@@ -1,6 +1,4 @@
1
- import { Component, ContentChildren, Directive, ElementRef, HostBinding, HostListener, booleanAttribute, inject, input, isDevMode, } from '@angular/core';
2
- import { Subject } from 'rxjs';
3
- import { takeUntil } from 'rxjs/operators';
1
+ import { Directive, ElementRef, HostBinding, booleanAttribute, inject, input, } from '@angular/core';
4
2
  import { TngUniqueIdService } from '../_shared/id';
5
3
  import * as i0 from "@angular/core";
6
4
  export function coerceTngInputNullableBoolean(value) {
@@ -23,17 +21,6 @@ function toAriaBoolean(value) {
23
21
  return null;
24
22
  return value ? 'true' : 'false';
25
23
  }
26
- function hasProjectedContent(element) {
27
- return Array.from(element.childNodes).some((node) => {
28
- if (node.nodeType === Node.ELEMENT_NODE) {
29
- return true;
30
- }
31
- if (node.nodeType === Node.TEXT_NODE) {
32
- return (node.textContent ?? '').trim().length > 0;
33
- }
34
- return false;
35
- });
36
- }
37
24
  export class TngInput {
38
25
  elementRef = inject((ElementRef));
39
26
  idService = inject(TngUniqueIdService);
@@ -165,245 +152,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImpor
165
152
  type: HostBinding,
166
153
  args: ['attr.required']
167
154
  }] } });
168
- export class TngInputLeading {
169
- hostElement = inject((ElementRef)).nativeElement;
170
- dataSlot = 'input-leading';
171
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputLeading, deps: [], target: i0.ɵɵFactoryTarget.Directive });
172
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.1", type: TngInputLeading, isStandalone: true, selector: "[tngInputLeading]", host: { properties: { "attr.data-slot": "this.dataSlot" } }, exportAs: ["tngInputLeading"], ngImport: i0 });
173
- }
174
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputLeading, decorators: [{
175
- type: Directive,
176
- args: [{
177
- selector: '[tngInputLeading]',
178
- exportAs: 'tngInputLeading',
179
- }]
180
- }], propDecorators: { dataSlot: [{
181
- type: HostBinding,
182
- args: ['attr.data-slot']
183
- }] } });
184
- export class TngInputTrailing {
185
- hostElement = inject((ElementRef)).nativeElement;
186
- dataSlot = 'input-trailing';
187
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputTrailing, deps: [], target: i0.ɵɵFactoryTarget.Directive });
188
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.1", type: TngInputTrailing, isStandalone: true, selector: "[tngInputTrailing]", host: { properties: { "attr.data-slot": "this.dataSlot" } }, exportAs: ["tngInputTrailing"], ngImport: i0 });
189
- }
190
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputTrailing, decorators: [{
191
- type: Directive,
192
- args: [{
193
- selector: '[tngInputTrailing]',
194
- exportAs: 'tngInputTrailing',
195
- }]
196
- }], propDecorators: { dataSlot: [{
197
- type: HostBinding,
198
- args: ['attr.data-slot']
199
- }] } });
200
- export class TngInputGroup {
201
- hasLeading = input(null, ...(ngDevMode ? [{ debugName: "hasLeading" }] : []));
202
- hasTrailing = input(null, ...(ngDevMode ? [{ debugName: "hasTrailing" }] : []));
203
- disabled = input(null, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
204
- invalid = input(null, ...(ngDevMode ? [{ debugName: "invalid" }] : []));
205
- readonly = input(null, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
206
- controlCount = input(null, ...(ngDevMode ? [{ debugName: "controlCount" }] : []));
207
- controls;
208
- leadingSlots;
209
- trailingSlots;
210
- hostElement = inject((ElementRef)).nativeElement;
211
- focused = false;
212
- destroyed$ = new Subject();
213
- validateSingleControl() {
214
- if (!isDevMode())
215
- return;
216
- if (!this.controls)
217
- return;
218
- const queriedCount = this.controls.length;
219
- const domCount = this.hostElement.querySelectorAll('[data-tng-input-control-proxy] input, [data-tng-input-control-proxy] textarea, input[tngInput], textarea[tngInput]').length;
220
- const count = this.controlCount() ?? (queriedCount > 0 ? queriedCount : domCount);
221
- if (count !== 1) {
222
- console.warn(`[tngInputGroup] Expected exactly 1 control (input/textarea with tngInput), but found ${count}.`, this.hostElement);
223
- }
224
- }
225
- ngAfterContentInit() {
226
- queueMicrotask(() => this.validateSingleControl());
227
- this.controls.changes
228
- .pipe(takeUntil(this.destroyed$))
229
- .subscribe(() => this.validateSingleControl());
230
- }
231
- ngOnDestroy() {
232
- this.destroyed$.next();
233
- this.destroyed$.complete();
234
- }
235
- dataSlot = 'input-group';
236
- get dataHasLeading() {
237
- return this.effectiveHasLeading() ? '' : null;
238
- }
239
- get dataHasTrailing() {
240
- return this.effectiveHasTrailing() ? '' : null;
241
- }
242
- get dataDisabled() {
243
- const override = this.disabled();
244
- if (override !== null)
245
- return override ? '' : null;
246
- const control = this.primaryControl();
247
- if (control !== null)
248
- return control.disabled() ? '' : null;
249
- const element = this.primaryControlElement();
250
- if (element === null)
251
- return null;
252
- return element.hasAttribute('disabled') ? '' : null;
253
- }
254
- get dataInvalid() {
255
- const override = this.invalid();
256
- if (override !== null)
257
- return override ? '' : null;
258
- const control = this.primaryControl();
259
- if (control !== null)
260
- return control.isInvalid() ? '' : null;
261
- const element = this.primaryControlElement();
262
- if (element === null)
263
- return null;
264
- if (element.getAttribute('aria-invalid') === 'true')
265
- return '';
266
- return element.matches(':invalid') ? '' : null;
267
- }
268
- get dataReadonly() {
269
- const override = this.readonly();
270
- if (override !== null)
271
- return override ? '' : null;
272
- const control = this.primaryControl();
273
- if (control !== null)
274
- return control.readonly() ? '' : null;
275
- const element = this.primaryControlElement();
276
- if (element === null)
277
- return null;
278
- return element.hasAttribute('readonly') ? '' : null;
279
- }
280
- get dataFocused() {
281
- return this.focused ? '' : null;
282
- }
283
- onFocusIn() {
284
- this.focused = true;
285
- }
286
- onFocusOut(event) {
287
- const nextTarget = event.relatedTarget;
288
- if (nextTarget instanceof Node && this.hostElement.contains(nextTarget))
289
- return;
290
- this.focused = false;
291
- }
292
- hasLeadingSlot() {
293
- const proxy = this.hostElement.querySelector('[data-tng-input-leading-proxy]');
294
- if (proxy instanceof HTMLElement)
295
- return hasProjectedContent(proxy);
296
- const slots = this.leadingSlots?.toArray() ?? [];
297
- return slots.some((slot) => hasProjectedContent(slot.hostElement));
298
- }
299
- hasTrailingSlot() {
300
- const proxy = this.hostElement.querySelector('[data-tng-input-trailing-proxy]');
301
- if (proxy instanceof HTMLElement)
302
- return hasProjectedContent(proxy);
303
- const slots = this.trailingSlots?.toArray() ?? [];
304
- return slots.some((slot) => hasProjectedContent(slot.hostElement));
305
- }
306
- effectiveHasLeading() {
307
- const override = this.hasLeading();
308
- if (override !== null)
309
- return override;
310
- return this.hasLeadingSlot();
311
- }
312
- effectiveHasTrailing() {
313
- const override = this.hasTrailing();
314
- if (override !== null)
315
- return override;
316
- return this.hasTrailingSlot();
317
- }
318
- primaryControl() {
319
- const controls = this.controls?.toArray() ?? [];
320
- return controls[0] ?? null;
321
- }
322
- primaryControlElement() {
323
- const element = this.hostElement.querySelector('[data-tng-input-control-proxy] input, [data-tng-input-control-proxy] textarea, input[tngInput], textarea[tngInput]');
324
- if (element instanceof HTMLInputElement ||
325
- element instanceof HTMLTextAreaElement) {
326
- return element;
327
- }
328
- return null;
329
- }
330
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
331
- 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: "leadingSlots", predicate: TngInputLeading, descendants: true }, { propertyName: "trailingSlots", predicate: TngInputTrailing, descendants: true }], exportAs: ["tngInputGroup"], ngImport: i0, template: `
332
- @if (hasLeadingSlot()) {
333
- <span class="tng-input-group-leading" data-slot="input-group-leading">
334
- <ng-content select="[tngInputLeading], [data-tng-input-leading-proxy]"></ng-content>
335
- </span>
336
- }
337
-
338
- <span class="tng-input-group-control" data-slot="input-group-control">
339
- <ng-content select="input[tngInput], textarea[tngInput], [data-tng-input-control-proxy]"></ng-content>
340
- </span>
341
-
342
- @if (hasTrailingSlot()) {
343
- <span class="tng-input-group-trailing" data-slot="input-group-trailing">
344
- <ng-content select="[tngInputTrailing], [data-tng-input-trailing-proxy]"></ng-content>
345
- </span>
346
- }
347
- `, isInline: true });
348
- }
349
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: TngInputGroup, decorators: [{
350
- type: Component,
351
- args: [{
352
- selector: 'tng-input-group, [tngInputGroup]',
353
- exportAs: 'tngInputGroup',
354
- template: `
355
- @if (hasLeadingSlot()) {
356
- <span class="tng-input-group-leading" data-slot="input-group-leading">
357
- <ng-content select="[tngInputLeading], [data-tng-input-leading-proxy]"></ng-content>
358
- </span>
359
- }
360
-
361
- <span class="tng-input-group-control" data-slot="input-group-control">
362
- <ng-content select="input[tngInput], textarea[tngInput], [data-tng-input-control-proxy]"></ng-content>
363
- </span>
364
-
365
- @if (hasTrailingSlot()) {
366
- <span class="tng-input-group-trailing" data-slot="input-group-trailing">
367
- <ng-content select="[tngInputTrailing], [data-tng-input-trailing-proxy]"></ng-content>
368
- </span>
369
- }
370
- `,
371
- }]
372
- }], propDecorators: { hasLeading: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasLeading", required: false }] }], hasTrailing: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasTrailing", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], controlCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlCount", required: false }] }], controls: [{
373
- type: ContentChildren,
374
- args: [TngInput, { descendants: true }]
375
- }], leadingSlots: [{
376
- type: ContentChildren,
377
- args: [TngInputLeading, { descendants: true }]
378
- }], trailingSlots: [{
379
- type: ContentChildren,
380
- args: [TngInputTrailing, { descendants: true }]
381
- }], dataSlot: [{
382
- type: HostBinding,
383
- args: ['attr.data-slot']
384
- }], dataHasLeading: [{
385
- type: HostBinding,
386
- args: ['attr.data-has-leading']
387
- }], dataHasTrailing: [{
388
- type: HostBinding,
389
- args: ['attr.data-has-trailing']
390
- }], dataDisabled: [{
391
- type: HostBinding,
392
- args: ['attr.data-disabled']
393
- }], dataInvalid: [{
394
- type: HostBinding,
395
- args: ['attr.data-invalid']
396
- }], dataReadonly: [{
397
- type: HostBinding,
398
- args: ['attr.data-readonly']
399
- }], dataFocused: [{
400
- type: HostBinding,
401
- args: ['attr.data-focused']
402
- }], onFocusIn: [{
403
- type: HostListener,
404
- args: ['focusin']
405
- }], onFocusOut: [{
406
- type: HostListener,
407
- args: ['focusout', ['$event']]
408
- }] } });
409
155
  //# sourceMappingURL=tng-input.js.map