@truenas/ui-components 0.2.1 → 0.2.3
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Overlay, OverlayPositionBuilder, OverlayModule } from '@angular/cdk/overlay';
|
|
2
2
|
import { TemplatePortal, ComponentPortal, PortalModule } from '@angular/cdk/portal';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { InjectionToken, inject, Renderer2, ElementRef, input, effect, Directive, ViewContainerRef, output, viewChild, computed, signal, forwardRef, Component, model, afterNextRender, ChangeDetectionStrategy, Injectable, isDevMode, ViewEncapsulation, contentChildren, HostListener, contentChild, ChangeDetectorRef, DestroyRef, TemplateRef, isSignal, untracked, IterableDiffers, Pipe, ApplicationRef, EnvironmentInjector, createComponent, PLATFORM_ID } from '@angular/core';
|
|
4
|
+
import { InjectionToken, inject, Renderer2, ElementRef, input, effect, Directive, ViewContainerRef, output, viewChild, computed, signal, forwardRef, Component, model, afterNextRender, ChangeDetectionStrategy, Injectable, isDevMode, ViewEncapsulation, contentChildren, HostListener, linkedSignal, contentChild, ChangeDetectorRef, DestroyRef, TemplateRef, isSignal, untracked, IterableDiffers, Pipe, ApplicationRef, EnvironmentInjector, createComponent, PLATFORM_ID } from '@angular/core';
|
|
5
5
|
import * as i1$3 from '@angular/forms';
|
|
6
6
|
import { NG_VALUE_ACCESSOR, FormsModule, NgControl, Validators } from '@angular/forms';
|
|
7
7
|
import { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';
|
|
@@ -17,10 +17,10 @@ import { firstValueFrom, BehaviorSubject, merge, Subject, take } from 'rxjs';
|
|
|
17
17
|
import { RouterLink } from '@angular/router';
|
|
18
18
|
import { filesize } from 'filesize';
|
|
19
19
|
import { CdkMenu, CdkMenuItem, CdkMenuTrigger } from '@angular/cdk/menu';
|
|
20
|
-
import { trigger, state, transition, style, animate } from '@angular/animations';
|
|
21
20
|
import { SPACE, ENTER, END, HOME, DOWN_ARROW, UP_ARROW, RIGHT_ARROW, LEFT_ARROW } from '@angular/cdk/keycodes';
|
|
22
21
|
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
|
|
23
22
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
23
|
+
import { trigger, state, transition, style, animate } from '@angular/animations';
|
|
24
24
|
import { SelectionModel, DataSource } from '@angular/cdk/collections';
|
|
25
25
|
import * as i2 from '@angular/cdk/tree';
|
|
26
26
|
import { CdkTree, CdkTreeModule, CdkTreeNode, CDK_TREE_NODE_OUTLET_NODE, CdkTreeNodeOutlet, CdkNestedTreeNode } from '@angular/cdk/tree';
|
|
@@ -2514,6 +2514,81 @@ var InputType;
|
|
|
2514
2514
|
InputType["Size"] = "size";
|
|
2515
2515
|
})(InputType || (InputType = {}));
|
|
2516
2516
|
|
|
2517
|
+
/**
|
|
2518
|
+
* Marks an icon name for inclusion in the TrueNAS UI sprite generation.
|
|
2519
|
+
*
|
|
2520
|
+
* This function serves two purposes:
|
|
2521
|
+
* 1. At runtime: Applies library-specific prefixes (e.g., mdi-, app-)
|
|
2522
|
+
* 2. At build time: Marker for the scanner to detect icons for sprite inclusion
|
|
2523
|
+
*
|
|
2524
|
+
* Use this when icon names are computed dynamically or come from variables,
|
|
2525
|
+
* to ensure they're included in the sprite at build time.
|
|
2526
|
+
*
|
|
2527
|
+
* @example
|
|
2528
|
+
* // Static icon name - automatically detected from template
|
|
2529
|
+
* <tn-icon name="folder"></tn-icon>
|
|
2530
|
+
*
|
|
2531
|
+
* @example
|
|
2532
|
+
* // Dynamic MDI icon
|
|
2533
|
+
* const iconName = condition ? tnIconMarker("pencil", "mdi") : tnIconMarker("delete", "mdi");
|
|
2534
|
+
* <tn-icon [name]="iconName"></tn-icon>
|
|
2535
|
+
*
|
|
2536
|
+
* @example
|
|
2537
|
+
* // Dynamic custom icon (consumer's own icon)
|
|
2538
|
+
* const logo = tnIconMarker("your-logo-name", "custom");
|
|
2539
|
+
* <tn-icon [name]="logo"></tn-icon>
|
|
2540
|
+
*
|
|
2541
|
+
* @example
|
|
2542
|
+
* // Array of dynamic icons
|
|
2543
|
+
* const actions = [
|
|
2544
|
+
* { name: "Save", icon: tnIconMarker("content-save", "mdi") },
|
|
2545
|
+
* { name: "Cancel", icon: tnIconMarker("close", "mdi") }
|
|
2546
|
+
* ];
|
|
2547
|
+
*
|
|
2548
|
+
* @param iconName - The icon name to mark for sprite inclusion
|
|
2549
|
+
* @param library - Optional library type: 'mdi', 'material', or 'custom'
|
|
2550
|
+
* @returns The icon name with appropriate prefix applied
|
|
2551
|
+
* @public
|
|
2552
|
+
*/
|
|
2553
|
+
function tnIconMarker(iconName, library) {
|
|
2554
|
+
// Apply library-specific prefixes
|
|
2555
|
+
if (library === 'mdi' && !iconName.startsWith('mdi-')) {
|
|
2556
|
+
return `mdi-${iconName}`;
|
|
2557
|
+
}
|
|
2558
|
+
if (library === 'custom' && !iconName.startsWith('app-')) {
|
|
2559
|
+
return `app-${iconName}`;
|
|
2560
|
+
}
|
|
2561
|
+
if (library === 'material' && !iconName.startsWith('mat-')) {
|
|
2562
|
+
return `mat-${iconName}`;
|
|
2563
|
+
}
|
|
2564
|
+
return iconName;
|
|
2565
|
+
}
|
|
2566
|
+
/**
|
|
2567
|
+
* INTERNAL LIBRARY USE ONLY
|
|
2568
|
+
*
|
|
2569
|
+
* Marks an icon name for inclusion in the sprite generation with library namespace.
|
|
2570
|
+
* This function MUST be used by library component code for custom icons.
|
|
2571
|
+
*
|
|
2572
|
+
* The TypeScript type enforces that the icon name starts with 'tn-' prefix,
|
|
2573
|
+
* which reserves this namespace exclusively for library-provided custom icons.
|
|
2574
|
+
*
|
|
2575
|
+
* @example
|
|
2576
|
+
* ```typescript
|
|
2577
|
+
* // ✅ Correct - Library component code
|
|
2578
|
+
* const icon = libIconMarker('tn-dataset');
|
|
2579
|
+
*
|
|
2580
|
+
* // ❌ Wrong - Will cause TypeScript error
|
|
2581
|
+
* const icon = libIconMarker('dataset');
|
|
2582
|
+
* ```
|
|
2583
|
+
*
|
|
2584
|
+
* @param iconName - The icon name with 'tn-' prefix (enforced by TypeScript)
|
|
2585
|
+
* @returns The same icon name (identity function)
|
|
2586
|
+
* @internal
|
|
2587
|
+
*/
|
|
2588
|
+
function libIconMarker(iconName) {
|
|
2589
|
+
return iconName;
|
|
2590
|
+
}
|
|
2591
|
+
|
|
2517
2592
|
// Ordered binary/decimal prefixes; the array index doubles as the power applied
|
|
2518
2593
|
// to the base (B = base^0, K = base^1, M = base^2, ...).
|
|
2519
2594
|
const UNIT_PREFIXES = ['B', 'K', 'M', 'G', 'T', 'P', 'E'];
|
|
@@ -2687,6 +2762,14 @@ class TnInputComponent {
|
|
|
2687
2762
|
* (e.g. `1.5 GiB`). Ignored unless `inputType` is `Size`.
|
|
2688
2763
|
*/
|
|
2689
2764
|
sizeRound = input(2, ...(ngDevMode ? [{ debugName: "sizeRound" }] : []));
|
|
2765
|
+
/**
|
|
2766
|
+
* Whether a `Password` field renders the built-in visibility toggle — the eye
|
|
2767
|
+
* button that switches the field between masked and plain-text display.
|
|
2768
|
+
* Defaults to true; set false for secrets that must never be revealed.
|
|
2769
|
+
* Setting `suffixIcon` suppresses the toggle automatically (a custom suffix
|
|
2770
|
+
* control replaces it). Ignored unless `inputType` is `Password`.
|
|
2771
|
+
*/
|
|
2772
|
+
showPasswordToggle = input(true, ...(ngDevMode ? [{ debugName: "showPasswordToggle" }] : []));
|
|
2690
2773
|
// Icon inputs
|
|
2691
2774
|
prefixIcon = input(undefined, ...(ngDevMode ? [{ debugName: "prefixIcon" }] : []));
|
|
2692
2775
|
prefixIconLibrary = input(undefined, ...(ngDevMode ? [{ debugName: "prefixIconLibrary" }] : []));
|
|
@@ -2709,8 +2792,28 @@ class TnInputComponent {
|
|
|
2709
2792
|
isSize = computed(() => this.inputType() === InputType.Size, ...(ngDevMode ? [{ debugName: "isSize" }] : []));
|
|
2710
2793
|
/** True when the field only accepts whole numbers (i.e. `allowDecimals` is false). */
|
|
2711
2794
|
integerOnly = computed(() => !this.allowDecimals(), ...(ngDevMode ? [{ debugName: "integerOnly" }] : []));
|
|
2712
|
-
/**
|
|
2713
|
-
|
|
2795
|
+
/** True when the field is a password field. */
|
|
2796
|
+
isPassword = computed(() => this.inputType() === InputType.Password, ...(ngDevMode ? [{ debugName: "isPassword" }] : []));
|
|
2797
|
+
/**
|
|
2798
|
+
* Whether the password is currently revealed. Not exposed as an input so a
|
|
2799
|
+
* reveal is always an explicit user gesture, and linked to the toggle's own
|
|
2800
|
+
* availability so a revealed value never outlives the control that revealed
|
|
2801
|
+
* it: whenever the toggle goes away (the field leaves password mode,
|
|
2802
|
+
* `showPasswordToggle` flips off, a `suffixIcon` replaces it) or the field
|
|
2803
|
+
* is disabled, the field snaps back to masked.
|
|
2804
|
+
*/
|
|
2805
|
+
passwordVisible = linkedSignal({ ...(ngDevMode ? { debugName: "passwordVisible" } : {}), source: () => this.hasPasswordToggle() && !this.isDisabled(),
|
|
2806
|
+
computation: () => false });
|
|
2807
|
+
/** The `type` attribute actually rendered. Number and size modes use a text input: number avoids the native type="number" footguns, size must accept unit letters. A revealed password renders as text — flipping the type attribute is the standard reveal mechanism and preserves value and caret. */
|
|
2808
|
+
resolvedType = computed(() => {
|
|
2809
|
+
if (this.isNumeric() || this.isSize()) {
|
|
2810
|
+
return InputType.PlainText;
|
|
2811
|
+
}
|
|
2812
|
+
if (this.isPassword() && this.passwordVisible()) {
|
|
2813
|
+
return InputType.PlainText;
|
|
2814
|
+
}
|
|
2815
|
+
return this.inputType();
|
|
2816
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedType" }] : []));
|
|
2714
2817
|
/** `inputmode` hint: numeric keypad for integers, decimal keypad otherwise. Null (omitted) outside number mode — size fields accept unit letters, so they keep the full keyboard. */
|
|
2715
2818
|
numericInputMode = computed(() => {
|
|
2716
2819
|
if (!this.isNumeric()) {
|
|
@@ -2720,6 +2823,30 @@ class TnInputComponent {
|
|
|
2720
2823
|
}, ...(ngDevMode ? [{ debugName: "numericInputMode" }] : []));
|
|
2721
2824
|
/** Number and size modes are always single-line; they win over `multiline` if both are set. */
|
|
2722
2825
|
showTextarea = computed(() => this.multiline() && !this.isNumeric() && !this.isSize(), ...(ngDevMode ? [{ debugName: "showTextarea" }] : []));
|
|
2826
|
+
/**
|
|
2827
|
+
* The visibility toggle renders only on single-line password fields (a
|
|
2828
|
+
* password+multiline combo renders a textarea, which has no `type` to flip),
|
|
2829
|
+
* and yields to a consumer-provided `suffixIcon` — a custom suffix control
|
|
2830
|
+
* replaces the built-in toggle rather than stacking a second button.
|
|
2831
|
+
*/
|
|
2832
|
+
hasPasswordToggle = computed(() => this.isPassword() && this.showPasswordToggle() && !this.showTextarea() && !this.hasSuffixIcon(), ...(ngDevMode ? [{ debugName: "hasPasswordToggle" }] : []));
|
|
2833
|
+
/**
|
|
2834
|
+
* Icon for the visibility toggle, mirroring the field's current state: a
|
|
2835
|
+
* slashed eye while masked, an open eye while revealed. The literal
|
|
2836
|
+
* `tnIconMarker` calls double as build-time markers that pull both icons
|
|
2837
|
+
* into the sprite.
|
|
2838
|
+
*/
|
|
2839
|
+
passwordToggleIcon = computed(() => this.passwordVisible() ? tnIconMarker('eye', 'mdi') : tnIconMarker('eye-off', 'mdi'), ...(ngDevMode ? [{ debugName: "passwordToggleIcon" }] : []));
|
|
2840
|
+
/**
|
|
2841
|
+
* Role-first test-id segments for the visibility toggle:
|
|
2842
|
+
* `button-toggle-password[-<testId>]`. The toggle is fixed field chrome, so
|
|
2843
|
+
* the role leads (matching the dialog-shell close/fullscreen convention) and
|
|
2844
|
+
* automation can target every password toggle with one prefix selector.
|
|
2845
|
+
*/
|
|
2846
|
+
passwordToggleTestId = computed(() => {
|
|
2847
|
+
const base = this.testId();
|
|
2848
|
+
return ['toggle-password', ...(Array.isArray(base) ? base : [base])];
|
|
2849
|
+
}, ...(ngDevMode ? [{ debugName: "passwordToggleTestId" }] : []));
|
|
2723
2850
|
// Unique per instance: a hard-coded id produced duplicate ids when multiple
|
|
2724
2851
|
// tn-inputs share a page (invalid HTML, and it breaks any future label `for=`,
|
|
2725
2852
|
// aria-describedby, or getElementById targeting this input).
|
|
@@ -2827,6 +2954,9 @@ class TnInputComponent {
|
|
|
2827
2954
|
}
|
|
2828
2955
|
this.onTouched();
|
|
2829
2956
|
}
|
|
2957
|
+
togglePasswordVisibility() {
|
|
2958
|
+
this.passwordVisible.update((visible) => !visible);
|
|
2959
|
+
}
|
|
2830
2960
|
/** Strips any character that can't appear in the current numeric mode (single leading '-', single '.' for decimals). */
|
|
2831
2961
|
sanitizeNumeric(raw) {
|
|
2832
2962
|
const allowDecimal = !this.integerOnly();
|
|
@@ -2855,13 +2985,13 @@ class TnInputComponent {
|
|
|
2855
2985
|
return Number.isNaN(parsed) ? null : parsed;
|
|
2856
2986
|
}
|
|
2857
2987
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2858
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnInputComponent, isStandalone: true, selector: "tn-input", inputs: { inputType: { classPropertyName: "inputType", publicName: "inputType", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, multiline: { classPropertyName: "multiline", publicName: "multiline", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, allowDecimals: { classPropertyName: "allowDecimals", publicName: "allowDecimals", isSignal: true, isRequired: false, transformFunction: null }, sizeStandard: { classPropertyName: "sizeStandard", publicName: "sizeStandard", isSignal: true, isRequired: false, transformFunction: null }, sizeDefaultUnit: { classPropertyName: "sizeDefaultUnit", publicName: "sizeDefaultUnit", isSignal: true, isRequired: false, transformFunction: null }, sizeRound: { classPropertyName: "sizeRound", publicName: "sizeRound", isSignal: true, isRequired: false, transformFunction: null }, prefixIcon: { classPropertyName: "prefixIcon", publicName: "prefixIcon", isSignal: true, isRequired: false, transformFunction: null }, prefixIconLibrary: { classPropertyName: "prefixIconLibrary", publicName: "prefixIconLibrary", isSignal: true, isRequired: false, transformFunction: null }, suffixIcon: { classPropertyName: "suffixIcon", publicName: "suffixIcon", isSignal: true, isRequired: false, transformFunction: null }, suffixIconLibrary: { classPropertyName: "suffixIconLibrary", publicName: "suffixIconLibrary", isSignal: true, isRequired: false, transformFunction: null }, suffixIconAriaLabel: { classPropertyName: "suffixIconAriaLabel", publicName: "suffixIconAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, suffixActionTestId: { classPropertyName: "suffixActionTestId", publicName: "suffixActionTestId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSuffixAction: "onSuffixAction" }, providers: [
|
|
2988
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnInputComponent, isStandalone: true, selector: "tn-input", inputs: { inputType: { classPropertyName: "inputType", publicName: "inputType", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, multiline: { classPropertyName: "multiline", publicName: "multiline", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, allowDecimals: { classPropertyName: "allowDecimals", publicName: "allowDecimals", isSignal: true, isRequired: false, transformFunction: null }, sizeStandard: { classPropertyName: "sizeStandard", publicName: "sizeStandard", isSignal: true, isRequired: false, transformFunction: null }, sizeDefaultUnit: { classPropertyName: "sizeDefaultUnit", publicName: "sizeDefaultUnit", isSignal: true, isRequired: false, transformFunction: null }, sizeRound: { classPropertyName: "sizeRound", publicName: "sizeRound", isSignal: true, isRequired: false, transformFunction: null }, showPasswordToggle: { classPropertyName: "showPasswordToggle", publicName: "showPasswordToggle", isSignal: true, isRequired: false, transformFunction: null }, prefixIcon: { classPropertyName: "prefixIcon", publicName: "prefixIcon", isSignal: true, isRequired: false, transformFunction: null }, prefixIconLibrary: { classPropertyName: "prefixIconLibrary", publicName: "prefixIconLibrary", isSignal: true, isRequired: false, transformFunction: null }, suffixIcon: { classPropertyName: "suffixIcon", publicName: "suffixIcon", isSignal: true, isRequired: false, transformFunction: null }, suffixIconLibrary: { classPropertyName: "suffixIconLibrary", publicName: "suffixIconLibrary", isSignal: true, isRequired: false, transformFunction: null }, suffixIconAriaLabel: { classPropertyName: "suffixIconAriaLabel", publicName: "suffixIconAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, suffixActionTestId: { classPropertyName: "suffixActionTestId", publicName: "suffixActionTestId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSuffixAction: "onSuffixAction" }, providers: [
|
|
2859
2989
|
{
|
|
2860
2990
|
provide: NG_VALUE_ACCESSOR,
|
|
2861
2991
|
useExisting: forwardRef(() => TnInputComponent),
|
|
2862
2992
|
multi: true
|
|
2863
2993
|
}
|
|
2864
|
-
], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"tn-input-container\"\n [class.tn-input-container--has-prefix]=\"hasPrefixIcon()\"\n [class.tn-input-container--has-suffix]=\"hasSuffixIcon()\"\n>\n <!-- Prefix icon -->\n @if (hasPrefixIcon()) {\n <tn-icon\n class=\"tn-input__prefix-icon\"\n size=\"sm\"\n aria-hidden=\"true\"\n [name]=\"prefixIcon()!\"\n [library]=\"prefixIconLibrary()\"\n />\n }\n\n <!-- Regular input field -->\n @if (!showTextarea()) {\n <input\n #inputEl\n class=\"tn-input\"\n tnTestIdType=\"input\"\n [id]=\"id\"\n [value]=\"value\"\n [type]=\"resolvedType()\"\n [attr.inputmode]=\"numericInputMode()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.name]=\"name()\"\n [tnTestId]=\"testId()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n />\n }\n\n <!-- Textarea field -->\n @if (showTextarea()) {\n <textarea\n #inputEl\n class=\"tn-input tn-textarea\"\n tnTestIdType=\"textarea\"\n [id]=\"id\"\n [value]=\"value\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.name]=\"name()\"\n [tnTestId]=\"testId()\"\n [rows]=\"rows()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n ></textarea>\n }\n\n <!-- Suffix icon action button -->\n @if (hasSuffixIcon()) {\n <button\n type=\"button\"\n class=\"tn-input__suffix-action\"\n tnTestIdType=\"button\"\n [tnTestId]=\"suffixActionTestId()\"\n [attr.aria-label]=\"suffixIconAriaLabel()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onSuffixAction.emit($event)\"\n >\n <tn-icon\n size=\"sm\"\n [name]=\"suffixIcon()!\"\n [library]=\"suffixIconLibrary()\"\n />\n </button>\n }\n</div>\n", styles: [".tn-input-container{position:relative;display:flex;align-items:center;width:100%;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif;background-color:var(--tn-bg1, #ffffff);border:1px solid var(--tn-lines, #d1d5db);border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.tn-input-container:focus-within{border-color:var(--tn-primary, #007bff);box-shadow:0 0 0 2px #007bff40}.tn-input-container:has(.tn-input:disabled){background-color:var(--tn-alt-bg1, #f8f9fa);opacity:.6;cursor:not-allowed}.tn-input-container:has(.tn-input.error){border-color:var(--tn-error, #dc3545)}.tn-input-container:has(.tn-input.error):focus-within{border-color:var(--tn-error, #dc3545);box-shadow:0 0 0 2px #dc354540}.tn-input{display:block;flex:1;min-width:0;min-height:2.5rem;padding:.5rem .75rem;font-size:1rem;line-height:1.5;color:var(--tn-fg1, #212529);background:transparent;border:none;border-radius:.375rem;outline:none;box-sizing:border-box}.tn-input::placeholder{color:var(--tn-alt-fg1, #999);opacity:1}.tn-input:disabled{color:var(--tn-fg2, #6c757d);cursor:not-allowed}.tn-input-container--has-prefix .tn-input{padding-left:.75rem;border-left:1px solid var(--tn-lines, #d1d5db);border-top-left-radius:0;border-bottom-left-radius:0}.tn-input-container--has-suffix .tn-input{padding-right:.25rem}.tn-input__prefix-icon{flex-shrink:0;margin-left:.75rem;margin-right:.75rem;color:var(--tn-fg2, #6c757d);pointer-events:none}.tn-input__suffix-action{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;margin-right:.375rem;padding:.25rem;border:none;border-radius:.25rem;background:transparent;color:var(--tn-fg2, #6c757d);cursor:pointer;transition:background-color .15s ease-in-out,color .15s ease-in-out}.tn-input__suffix-action:hover:not(:disabled){background-color:var(--tn-bg3, #f3f4f6);color:var(--tn-fg1, #1f2937)}.tn-input__suffix-action:focus-visible{outline:2px solid var(--tn-primary, #2563eb);outline-offset:1px}.tn-input__suffix-action:disabled{cursor:not-allowed;pointer-events:none}.tn-textarea{min-height:6rem;resize:vertical;line-height:1.4}@media(prefers-reduced-motion:reduce){.tn-input-container,.tn-input__suffix-action{transition:none}}@media(prefers-contrast:high){.tn-input-container{border-width:2px}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: A11yModule }, { kind: "component", type: TnIconComponent, selector: "tn-icon", inputs: ["name", "size", "color", "tooltip", "ariaLabel", "library", "testId", "fullSize", "customSize"] }, { kind: "directive", type: TnTestIdDirective, selector: "[tnTestId]", inputs: ["tnTestId", "tnTestIdType"] }] });
|
|
2994
|
+
], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"tn-input-container\"\n [class.tn-input-container--has-prefix]=\"hasPrefixIcon()\"\n [class.tn-input-container--has-suffix]=\"hasSuffixIcon() || hasPasswordToggle()\"\n>\n <!-- Prefix icon -->\n @if (hasPrefixIcon()) {\n <tn-icon\n class=\"tn-input__prefix-icon\"\n size=\"sm\"\n aria-hidden=\"true\"\n [name]=\"prefixIcon()!\"\n [library]=\"prefixIconLibrary()\"\n />\n }\n\n <!-- Regular input field -->\n @if (!showTextarea()) {\n <input\n #inputEl\n class=\"tn-input\"\n tnTestIdType=\"input\"\n [id]=\"id\"\n [value]=\"value\"\n [type]=\"resolvedType()\"\n [attr.inputmode]=\"numericInputMode()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.name]=\"name()\"\n [tnTestId]=\"testId()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n />\n }\n\n <!-- Textarea field -->\n @if (showTextarea()) {\n <textarea\n #inputEl\n class=\"tn-input tn-textarea\"\n tnTestIdType=\"textarea\"\n [id]=\"id\"\n [value]=\"value\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.name]=\"name()\"\n [tnTestId]=\"testId()\"\n [rows]=\"rows()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n ></textarea>\n }\n\n <!-- Suffix icon action button -->\n @if (hasSuffixIcon()) {\n <button\n type=\"button\"\n class=\"tn-input__suffix-action\"\n tnTestIdType=\"button\"\n [tnTestId]=\"suffixActionTestId()\"\n [attr.aria-label]=\"suffixIconAriaLabel()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onSuffixAction.emit($event)\"\n >\n <tn-icon\n size=\"sm\"\n [name]=\"suffixIcon()!\"\n [library]=\"suffixIconLibrary()\"\n />\n </button>\n }\n\n <!-- Password visibility toggle. State is conveyed via the swapping\n aria-label alone \u2014 no aria-pressed, which would contradict a label that\n already names the action (\"Hide password, pressed\" is ambiguous). -->\n @if (hasPasswordToggle()) {\n <button\n type=\"button\"\n class=\"tn-input__visibility-toggle\"\n tnTestIdType=\"button\"\n [tnTestId]=\"passwordToggleTestId()\"\n [attr.aria-label]=\"passwordVisible() ? 'Hide password' : 'Show password'\"\n [disabled]=\"isDisabled()\"\n (click)=\"togglePasswordVisibility()\"\n >\n <tn-icon size=\"sm\" aria-hidden=\"true\" [name]=\"passwordToggleIcon()\" />\n </button>\n }\n</div>\n", styles: [".tn-input-container{position:relative;display:flex;align-items:center;width:100%;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif;background-color:var(--tn-bg1, #ffffff);border:1px solid var(--tn-lines, #d1d5db);border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.tn-input-container:focus-within{border-color:var(--tn-primary, #007bff);box-shadow:0 0 0 2px #007bff40}.tn-input-container:has(.tn-input:disabled){background-color:var(--tn-alt-bg1, #f8f9fa);opacity:.6;cursor:not-allowed}.tn-input-container:has(.tn-input.error){border-color:var(--tn-error, #dc3545)}.tn-input-container:has(.tn-input.error):focus-within{border-color:var(--tn-error, #dc3545);box-shadow:0 0 0 2px #dc354540}.tn-input{display:block;flex:1;min-width:0;min-height:2.5rem;padding:.5rem .75rem;font-size:1rem;line-height:1.5;color:var(--tn-fg1, #212529);background:transparent;border:none;border-radius:.375rem;outline:none;box-sizing:border-box}.tn-input::placeholder{color:var(--tn-alt-fg1, #999);opacity:1}.tn-input:disabled{color:var(--tn-fg2, #6c757d);cursor:not-allowed}.tn-input-container--has-prefix .tn-input{padding-left:.75rem;border-left:1px solid var(--tn-lines, #d1d5db);border-top-left-radius:0;border-bottom-left-radius:0}.tn-input-container--has-suffix .tn-input{padding-right:.25rem}.tn-input__prefix-icon{flex-shrink:0;margin-left:.75rem;margin-right:.75rem;color:var(--tn-fg2, #6c757d);pointer-events:none}.tn-input__suffix-action,.tn-input__visibility-toggle{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;margin-right:.375rem;padding:.25rem;border:none;border-radius:.25rem;background:transparent;color:var(--tn-fg2, #6c757d);cursor:pointer;transition:background-color .15s ease-in-out,color .15s ease-in-out}.tn-input__suffix-action:hover:not(:disabled),.tn-input__visibility-toggle:hover:not(:disabled){background-color:var(--tn-bg3, #f3f4f6);color:var(--tn-fg1, #1f2937)}.tn-input__suffix-action:focus-visible,.tn-input__visibility-toggle:focus-visible{outline:2px solid var(--tn-primary, #2563eb);outline-offset:1px}.tn-input__suffix-action:disabled,.tn-input__visibility-toggle:disabled{cursor:not-allowed;pointer-events:none}.tn-textarea{min-height:6rem;resize:vertical;line-height:1.4}@media(prefers-reduced-motion:reduce){.tn-input-container,.tn-input__suffix-action,.tn-input__visibility-toggle{transition:none}}@media(prefers-contrast:high){.tn-input-container{border-width:2px}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: A11yModule }, { kind: "component", type: TnIconComponent, selector: "tn-icon", inputs: ["name", "size", "color", "tooltip", "ariaLabel", "library", "testId", "fullSize", "customSize"] }, { kind: "directive", type: TnTestIdDirective, selector: "[tnTestId]", inputs: ["tnTestId", "tnTestIdType"] }] });
|
|
2865
2995
|
}
|
|
2866
2996
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnInputComponent, decorators: [{
|
|
2867
2997
|
type: Component,
|
|
@@ -2871,8 +3001,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
2871
3001
|
useExisting: forwardRef(() => TnInputComponent),
|
|
2872
3002
|
multi: true
|
|
2873
3003
|
}
|
|
2874
|
-
], template: "<div\n class=\"tn-input-container\"\n [class.tn-input-container--has-prefix]=\"hasPrefixIcon()\"\n [class.tn-input-container--has-suffix]=\"hasSuffixIcon()\"\n>\n <!-- Prefix icon -->\n @if (hasPrefixIcon()) {\n <tn-icon\n class=\"tn-input__prefix-icon\"\n size=\"sm\"\n aria-hidden=\"true\"\n [name]=\"prefixIcon()!\"\n [library]=\"prefixIconLibrary()\"\n />\n }\n\n <!-- Regular input field -->\n @if (!showTextarea()) {\n <input\n #inputEl\n class=\"tn-input\"\n tnTestIdType=\"input\"\n [id]=\"id\"\n [value]=\"value\"\n [type]=\"resolvedType()\"\n [attr.inputmode]=\"numericInputMode()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.name]=\"name()\"\n [tnTestId]=\"testId()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n />\n }\n\n <!-- Textarea field -->\n @if (showTextarea()) {\n <textarea\n #inputEl\n class=\"tn-input tn-textarea\"\n tnTestIdType=\"textarea\"\n [id]=\"id\"\n [value]=\"value\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.name]=\"name()\"\n [tnTestId]=\"testId()\"\n [rows]=\"rows()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n ></textarea>\n }\n\n <!-- Suffix icon action button -->\n @if (hasSuffixIcon()) {\n <button\n type=\"button\"\n class=\"tn-input__suffix-action\"\n tnTestIdType=\"button\"\n [tnTestId]=\"suffixActionTestId()\"\n [attr.aria-label]=\"suffixIconAriaLabel()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onSuffixAction.emit($event)\"\n >\n <tn-icon\n size=\"sm\"\n [name]=\"suffixIcon()!\"\n [library]=\"suffixIconLibrary()\"\n />\n </button>\n }\n</div>\n", styles: [".tn-input-container{position:relative;display:flex;align-items:center;width:100%;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif;background-color:var(--tn-bg1, #ffffff);border:1px solid var(--tn-lines, #d1d5db);border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.tn-input-container:focus-within{border-color:var(--tn-primary, #007bff);box-shadow:0 0 0 2px #007bff40}.tn-input-container:has(.tn-input:disabled){background-color:var(--tn-alt-bg1, #f8f9fa);opacity:.6;cursor:not-allowed}.tn-input-container:has(.tn-input.error){border-color:var(--tn-error, #dc3545)}.tn-input-container:has(.tn-input.error):focus-within{border-color:var(--tn-error, #dc3545);box-shadow:0 0 0 2px #dc354540}.tn-input{display:block;flex:1;min-width:0;min-height:2.5rem;padding:.5rem .75rem;font-size:1rem;line-height:1.5;color:var(--tn-fg1, #212529);background:transparent;border:none;border-radius:.375rem;outline:none;box-sizing:border-box}.tn-input::placeholder{color:var(--tn-alt-fg1, #999);opacity:1}.tn-input:disabled{color:var(--tn-fg2, #6c757d);cursor:not-allowed}.tn-input-container--has-prefix .tn-input{padding-left:.75rem;border-left:1px solid var(--tn-lines, #d1d5db);border-top-left-radius:0;border-bottom-left-radius:0}.tn-input-container--has-suffix .tn-input{padding-right:.25rem}.tn-input__prefix-icon{flex-shrink:0;margin-left:.75rem;margin-right:.75rem;color:var(--tn-fg2, #6c757d);pointer-events:none}.tn-input__suffix-action{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;margin-right:.375rem;padding:.25rem;border:none;border-radius:.25rem;background:transparent;color:var(--tn-fg2, #6c757d);cursor:pointer;transition:background-color .15s ease-in-out,color .15s ease-in-out}.tn-input__suffix-action:hover:not(:disabled){background-color:var(--tn-bg3, #f3f4f6);color:var(--tn-fg1, #1f2937)}.tn-input__suffix-action:focus-visible{outline:2px solid var(--tn-primary, #2563eb);outline-offset:1px}.tn-input__suffix-action:disabled{cursor:not-allowed;pointer-events:none}.tn-textarea{min-height:6rem;resize:vertical;line-height:1.4}@media(prefers-reduced-motion:reduce){.tn-input-container,.tn-input__suffix-action{transition:none}}@media(prefers-contrast:high){.tn-input-container{border-width:2px}}\n"] }]
|
|
2875
|
-
}], propDecorators: { inputEl: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }], inputType: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputType", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], multiline: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiline", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], allowDecimals: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowDecimals", required: false }] }], sizeStandard: [{ type: i0.Input, args: [{ isSignal: true, alias: "sizeStandard", required: false }] }], sizeDefaultUnit: [{ type: i0.Input, args: [{ isSignal: true, alias: "sizeDefaultUnit", required: false }] }], sizeRound: [{ type: i0.Input, args: [{ isSignal: true, alias: "sizeRound", required: false }] }], prefixIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixIcon", required: false }] }], prefixIconLibrary: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixIconLibrary", required: false }] }], suffixIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixIcon", required: false }] }], suffixIconLibrary: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixIconLibrary", required: false }] }], suffixIconAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixIconAriaLabel", required: false }] }], suffixActionTestId: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixActionTestId", required: false }] }], onSuffixAction: [{ type: i0.Output, args: ["onSuffixAction"] }] } });
|
|
3004
|
+
], template: "<div\n class=\"tn-input-container\"\n [class.tn-input-container--has-prefix]=\"hasPrefixIcon()\"\n [class.tn-input-container--has-suffix]=\"hasSuffixIcon() || hasPasswordToggle()\"\n>\n <!-- Prefix icon -->\n @if (hasPrefixIcon()) {\n <tn-icon\n class=\"tn-input__prefix-icon\"\n size=\"sm\"\n aria-hidden=\"true\"\n [name]=\"prefixIcon()!\"\n [library]=\"prefixIconLibrary()\"\n />\n }\n\n <!-- Regular input field -->\n @if (!showTextarea()) {\n <input\n #inputEl\n class=\"tn-input\"\n tnTestIdType=\"input\"\n [id]=\"id\"\n [value]=\"value\"\n [type]=\"resolvedType()\"\n [attr.inputmode]=\"numericInputMode()\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.name]=\"name()\"\n [tnTestId]=\"testId()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n />\n }\n\n <!-- Textarea field -->\n @if (showTextarea()) {\n <textarea\n #inputEl\n class=\"tn-input tn-textarea\"\n tnTestIdType=\"textarea\"\n [id]=\"id\"\n [value]=\"value\"\n [attr.aria-label]=\"ariaLabel()\"\n [attr.placeholder]=\"placeholder()\"\n [attr.autocomplete]=\"autocomplete()\"\n [attr.name]=\"name()\"\n [tnTestId]=\"testId()\"\n [rows]=\"rows()\"\n [disabled]=\"isDisabled()\"\n [readonly]=\"readonly()\"\n [required]=\"required()\"\n (input)=\"onValueChange($event)\"\n (blur)=\"onBlur()\"\n ></textarea>\n }\n\n <!-- Suffix icon action button -->\n @if (hasSuffixIcon()) {\n <button\n type=\"button\"\n class=\"tn-input__suffix-action\"\n tnTestIdType=\"button\"\n [tnTestId]=\"suffixActionTestId()\"\n [attr.aria-label]=\"suffixIconAriaLabel()\"\n [disabled]=\"isDisabled()\"\n (click)=\"onSuffixAction.emit($event)\"\n >\n <tn-icon\n size=\"sm\"\n [name]=\"suffixIcon()!\"\n [library]=\"suffixIconLibrary()\"\n />\n </button>\n }\n\n <!-- Password visibility toggle. State is conveyed via the swapping\n aria-label alone \u2014 no aria-pressed, which would contradict a label that\n already names the action (\"Hide password, pressed\" is ambiguous). -->\n @if (hasPasswordToggle()) {\n <button\n type=\"button\"\n class=\"tn-input__visibility-toggle\"\n tnTestIdType=\"button\"\n [tnTestId]=\"passwordToggleTestId()\"\n [attr.aria-label]=\"passwordVisible() ? 'Hide password' : 'Show password'\"\n [disabled]=\"isDisabled()\"\n (click)=\"togglePasswordVisibility()\"\n >\n <tn-icon size=\"sm\" aria-hidden=\"true\" [name]=\"passwordToggleIcon()\" />\n </button>\n }\n</div>\n", styles: [".tn-input-container{position:relative;display:flex;align-items:center;width:100%;font-family:var(--tn-font-family-body, \"Inter\"),sans-serif;background-color:var(--tn-bg1, #ffffff);border:1px solid var(--tn-lines, #d1d5db);border-radius:.375rem;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.tn-input-container:focus-within{border-color:var(--tn-primary, #007bff);box-shadow:0 0 0 2px #007bff40}.tn-input-container:has(.tn-input:disabled){background-color:var(--tn-alt-bg1, #f8f9fa);opacity:.6;cursor:not-allowed}.tn-input-container:has(.tn-input.error){border-color:var(--tn-error, #dc3545)}.tn-input-container:has(.tn-input.error):focus-within{border-color:var(--tn-error, #dc3545);box-shadow:0 0 0 2px #dc354540}.tn-input{display:block;flex:1;min-width:0;min-height:2.5rem;padding:.5rem .75rem;font-size:1rem;line-height:1.5;color:var(--tn-fg1, #212529);background:transparent;border:none;border-radius:.375rem;outline:none;box-sizing:border-box}.tn-input::placeholder{color:var(--tn-alt-fg1, #999);opacity:1}.tn-input:disabled{color:var(--tn-fg2, #6c757d);cursor:not-allowed}.tn-input-container--has-prefix .tn-input{padding-left:.75rem;border-left:1px solid var(--tn-lines, #d1d5db);border-top-left-radius:0;border-bottom-left-radius:0}.tn-input-container--has-suffix .tn-input{padding-right:.25rem}.tn-input__prefix-icon{flex-shrink:0;margin-left:.75rem;margin-right:.75rem;color:var(--tn-fg2, #6c757d);pointer-events:none}.tn-input__suffix-action,.tn-input__visibility-toggle{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;margin-right:.375rem;padding:.25rem;border:none;border-radius:.25rem;background:transparent;color:var(--tn-fg2, #6c757d);cursor:pointer;transition:background-color .15s ease-in-out,color .15s ease-in-out}.tn-input__suffix-action:hover:not(:disabled),.tn-input__visibility-toggle:hover:not(:disabled){background-color:var(--tn-bg3, #f3f4f6);color:var(--tn-fg1, #1f2937)}.tn-input__suffix-action:focus-visible,.tn-input__visibility-toggle:focus-visible{outline:2px solid var(--tn-primary, #2563eb);outline-offset:1px}.tn-input__suffix-action:disabled,.tn-input__visibility-toggle:disabled{cursor:not-allowed;pointer-events:none}.tn-textarea{min-height:6rem;resize:vertical;line-height:1.4}@media(prefers-reduced-motion:reduce){.tn-input-container,.tn-input__suffix-action,.tn-input__visibility-toggle{transition:none}}@media(prefers-contrast:high){.tn-input-container{border-width:2px}}\n"] }]
|
|
3005
|
+
}], propDecorators: { inputEl: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }], inputType: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputType", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], multiline: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiline", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], allowDecimals: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowDecimals", required: false }] }], sizeStandard: [{ type: i0.Input, args: [{ isSignal: true, alias: "sizeStandard", required: false }] }], sizeDefaultUnit: [{ type: i0.Input, args: [{ isSignal: true, alias: "sizeDefaultUnit", required: false }] }], sizeRound: [{ type: i0.Input, args: [{ isSignal: true, alias: "sizeRound", required: false }] }], showPasswordToggle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPasswordToggle", required: false }] }], prefixIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixIcon", required: false }] }], prefixIconLibrary: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixIconLibrary", required: false }] }], suffixIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixIcon", required: false }] }], suffixIconLibrary: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixIconLibrary", required: false }] }], suffixIconAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixIconAriaLabel", required: false }] }], suffixActionTestId: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixActionTestId", required: false }] }], onSuffixAction: [{ type: i0.Output, args: ["onSuffixAction"] }] } });
|
|
2876
3006
|
|
|
2877
3007
|
/**
|
|
2878
3008
|
* Harness for interacting with tn-icon in tests.
|
|
@@ -3132,6 +3262,7 @@ class TnInputHarness extends ComponentHarness {
|
|
|
3132
3262
|
prefixIconEl = this.locatorForOptional('tn-icon.tn-input__prefix-icon');
|
|
3133
3263
|
suffixButton = this.locatorForOptional('.tn-input__suffix-action');
|
|
3134
3264
|
suffixIconEl = this.locatorForOptional(TnIconHarness.with({ ancestor: '.tn-input__suffix-action' }));
|
|
3265
|
+
visibilityToggle = this.locatorForOptional('.tn-input__visibility-toggle');
|
|
3135
3266
|
/**
|
|
3136
3267
|
* Gets a `HarnessPredicate` that can be used to search for an input
|
|
3137
3268
|
* with specific attributes.
|
|
@@ -3390,6 +3521,43 @@ class TnInputHarness extends ComponentHarness {
|
|
|
3390
3521
|
}
|
|
3391
3522
|
return button.click();
|
|
3392
3523
|
}
|
|
3524
|
+
/**
|
|
3525
|
+
* Checks whether the password visibility toggle is present.
|
|
3526
|
+
*
|
|
3527
|
+
* @returns Promise resolving to true if the toggle button exists.
|
|
3528
|
+
*/
|
|
3529
|
+
async hasPasswordToggle() {
|
|
3530
|
+
const toggle = await this.visibilityToggle();
|
|
3531
|
+
return toggle !== null;
|
|
3532
|
+
}
|
|
3533
|
+
/**
|
|
3534
|
+
* Whether the password is currently revealed (the field renders as plain text).
|
|
3535
|
+
*
|
|
3536
|
+
* Only meaningful on password-type inputs; resolves false while masked.
|
|
3537
|
+
*
|
|
3538
|
+
* @returns Promise resolving to true when the value is shown in plain text.
|
|
3539
|
+
*/
|
|
3540
|
+
async isPasswordRevealed() {
|
|
3541
|
+
const toggle = await this.visibilityToggle();
|
|
3542
|
+
if (!toggle) {
|
|
3543
|
+
return false;
|
|
3544
|
+
}
|
|
3545
|
+
const input = await this.inputEl();
|
|
3546
|
+
return (await input.getProperty('type')) === 'text';
|
|
3547
|
+
}
|
|
3548
|
+
/**
|
|
3549
|
+
* Clicks the password visibility toggle, switching between masked and
|
|
3550
|
+
* plain-text display.
|
|
3551
|
+
*
|
|
3552
|
+
* @returns Promise that resolves when the click action is complete.
|
|
3553
|
+
*/
|
|
3554
|
+
async togglePasswordVisibility() {
|
|
3555
|
+
const toggle = await this.visibilityToggle();
|
|
3556
|
+
if (!toggle) {
|
|
3557
|
+
throw new Error('No password visibility toggle found on this input.');
|
|
3558
|
+
}
|
|
3559
|
+
return toggle.click();
|
|
3560
|
+
}
|
|
3393
3561
|
/**
|
|
3394
3562
|
* Focuses the input element.
|
|
3395
3563
|
*
|
|
@@ -4256,28 +4424,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
4256
4424
|
], template: "<div [ngClass]=\"classes()\">\n <!-- Header section -->\n @if (hasHeader()) {\n <div class=\"tn-card__header\">\n <div class=\"tn-card__header-left\">\n <ng-content select=\"[tnCardHeader]\" />\n @if (!projectedHeader() && title()) {\n <h3\n class=\"tn-card__title\"\n [class.tn-card__title--link]=\"titleLink()\"\n [attr.tabindex]=\"titleLink() ? 0 : null\"\n [attr.role]=\"titleLink() ? 'button' : null\"\n (click)=\"onTitleClick()\"\n (keydown.enter)=\"onTitleClick()\"\n (keydown.space)=\"onTitleClick()\">\n {{ title() }}\n </h3>\n }\n </div>\n\n @if (hasHeaderRight()) {\n <div class=\"tn-card__header-right\">\n <!-- Header Status -->\n @if (headerStatus(); as status) {\n <div\n class=\"tn-card__status\"\n [ngClass]=\"getStatusClass(status?.type)\"\n [tnTestId]=\"status.testId\">\n {{ status.label }}\n </div>\n }\n\n <!-- Header Control (Slide Toggle) -->\n @if (headerControl(); as control) {\n <div class=\"tn-card__control\">\n <tn-slide-toggle\n [label]=\"control.label\"\n [checked]=\"control.checked\"\n [disabled]=\"control.disabled || false\"\n [testId]=\"control.testId\"\n (change)=\"onControlChange($event)\" />\n </div>\n }\n\n <!-- Header Menu -->\n @if (headerMenu(); as menu) {\n @if (menu.length) {\n <div class=\"tn-card__menu\">\n <tn-icon-button\n name=\"dots-vertical\"\n library=\"mdi\"\n size=\"md\"\n ariaLabel=\"Card menu\"\n [testId]=\"headerMenuTriggerTestId()\"\n [tnMenuTriggerFor]=\"cardMenu\" />\n <tn-menu\n #cardMenu\n [items]=\"menu\"\n (menuItemClick)=\"onHeaderMenuItemClick($event)\" />\n </div>\n }\n }\n </div>\n }\n </div>\n }\n\n <!-- Content section -->\n <div class=\"tn-card__content\">\n <ng-content />\n </div>\n\n <!-- Footer section -->\n @if (hasFooter()) {\n <div class=\"tn-card__footer\">\n <div class=\"tn-card__footer-left\">\n @if (footerLink(); as link) {\n <button\n type=\"button\"\n class=\"tn-card__footer-link\"\n tnTestIdType=\"link\"\n [tnTestId]=\"link.testId\"\n (click)=\"link.handler()\">\n {{ link.label }}\n </button>\n }\n </div>\n\n <div class=\"tn-card__footer-right\">\n @if (secondaryAction(); as action) {\n <tn-button\n variant=\"outline\"\n color=\"default\"\n [label]=\"action.label\"\n [disabled]=\"action.disabled || false\"\n [testId]=\"action.testId\"\n (click)=\"action.handler()\" />\n }\n\n @if (primaryAction(); as action) {\n <tn-button\n variant=\"filled\"\n color=\"primary\"\n [label]=\"action.label\"\n [disabled]=\"action.disabled || false\"\n [testId]=\"action.testId\"\n (click)=\"action.handler()\" />\n }\n </div>\n </div>\n }\n</div>", styles: [".tn-card{height:100%;display:flex;flex-direction:column;border-radius:8px;transition:box-shadow .3s ease;overflow:hidden}.tn-card--elevation-none{box-shadow:none}.tn-card--elevation-low{box-shadow:0 1px 3px #0000001a}.tn-card--elevation-medium{box-shadow:0 4px 6px #0000001a}.tn-card--elevation-high{box-shadow:0 10px 15px #0000001a}.tn-card--bordered{border:1px solid var(--tn-lines, #e5e7eb)}.tn-card--background{background-color:var(--tn-bg2, #ffffff)}.tn-card--padding-small .tn-card__header{padding:12px 16px}.tn-card--padding-medium .tn-card__header{padding:16px 24px}.tn-card--padding-large .tn-card__header{padding:24px 32px}.tn-card--content-padding-none .tn-card__content{padding:0}.tn-card--content-padding-small .tn-card__content{padding:16px}.tn-card--content-padding-medium .tn-card__content{padding:24px}.tn-card--content-padding-large .tn-card__content{padding:32px}.tn-card__content{flex:1;min-height:0;font-size:14px}.tn-card__header{display:flex;align-items:center;justify-content:space-between;gap:16px;border-bottom:1px solid var(--tn-lines, #e5e7eb)}.tn-card__header-left{flex:1;min-width:0}.tn-card__header-right{display:flex;align-items:center;gap:12px;flex-shrink:0}.tn-card__title{margin:0;font-size:1.125rem;font-weight:600;color:var(--tn-fg1, #1f2937);line-height:1.5}.tn-card__title--link{cursor:pointer;transition:color .2s ease}.tn-card__title--link:hover{color:var(--tn-primary, #2563eb)}.tn-card__status{display:inline-flex;align-items:center;padding:4px 12px;border-radius:12px;font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.5px}.tn-card__status--success{background-color:#10b9811a;color:var(--tn-success, #10b981)}.tn-card__status--warning{background-color:#f59e0b1a;color:var(--tn-warning, #f59e0b)}.tn-card__status--error{background-color:#ef44441a;color:var(--tn-error, #ef4444)}.tn-card__status--info{background-color:#3b82f61a;color:var(--tn-info, #3b82f6)}.tn-card__status--neutral{background-color:#6b72801a;color:var(--tn-fg2, #6b7280)}.tn-card__control,.tn-card__menu{display:flex;align-items:center}.tn-card__footer{display:flex;align-items:center;justify-content:space-between;gap:16px;border-top:1px solid var(--tn-lines, #e5e7eb);padding:16px 24px}.tn-card--padding-small .tn-card__footer{padding:12px 16px}.tn-card--padding-large .tn-card__footer{padding:24px 32px}.tn-card__footer-left{flex:1;min-width:0}.tn-card__footer-right{display:flex;align-items:center;gap:8px;flex-shrink:0}.tn-card__footer-link{border:none;background:transparent;color:var(--tn-primary, #2563eb);font-size:1rem;font-weight:600;cursor:pointer;padding:0;text-decoration:none;transition:color .2s ease}.tn-card__footer-link:hover{color:var(--tn-primary-dark, #1d4ed8);text-decoration:underline}.tn-card__footer-link:focus{outline:2px solid var(--tn-primary, #2563eb);outline-offset:2px;border-radius:2px}\n"] }]
|
|
4257
4425
|
}], ctorParameters: () => [], propDecorators: { projectedHeader: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TnCardHeaderDirective), { isSignal: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], titleLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleLink", required: false }] }], elevation: [{ type: i0.Input, args: [{ isSignal: true, alias: "elevation", required: false }] }], padding: [{ type: i0.Input, args: [{ isSignal: true, alias: "padding", required: false }] }], padContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "padContent", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], background: [{ type: i0.Input, args: [{ isSignal: true, alias: "background", required: false }] }], headerStatus: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerStatus", required: false }] }], headerControl: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerControl", required: false }] }], headerMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerMenu", required: false }] }], headerMenuTriggerTestId: [{ type: i0.Input, args: [{ isSignal: true, alias: "headerMenuTriggerTestId", required: false }] }], primaryAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "primaryAction", required: false }] }], secondaryAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "secondaryAction", required: false }] }], footerLink: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerLink", required: false }] }] } });
|
|
4258
4426
|
|
|
4259
|
-
const expandCollapseAnimation = trigger('expandCollapse', [
|
|
4260
|
-
state('collapsed', style({
|
|
4261
|
-
height: '0px',
|
|
4262
|
-
opacity: 0,
|
|
4263
|
-
overflow: 'hidden',
|
|
4264
|
-
display: 'none'
|
|
4265
|
-
})),
|
|
4266
|
-
state('expanded', style({
|
|
4267
|
-
height: '*',
|
|
4268
|
-
opacity: 1,
|
|
4269
|
-
overflow: 'visible',
|
|
4270
|
-
display: 'block'
|
|
4271
|
-
})),
|
|
4272
|
-
transition('collapsed => expanded', [
|
|
4273
|
-
style({ display: 'block', height: '0px', opacity: 0 }),
|
|
4274
|
-
animate('300ms cubic-bezier(0.4, 0, 0.2, 1)', style({ height: '*', opacity: 1 }))
|
|
4275
|
-
]),
|
|
4276
|
-
transition('expanded => collapsed', [
|
|
4277
|
-
animate('300ms cubic-bezier(0.4, 0, 0.2, 1)', style({ height: '0px', opacity: 0 })),
|
|
4278
|
-
style({ display: 'none' })
|
|
4279
|
-
])
|
|
4280
|
-
]);
|
|
4281
4427
|
class TnExpansionPanelComponent {
|
|
4282
4428
|
title = input(undefined, ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
4283
4429
|
elevation = input('medium', ...(ngDevMode ? [{ debugName: "elevation" }] : []));
|
|
@@ -4335,11 +4481,11 @@ class TnExpansionPanelComponent {
|
|
|
4335
4481
|
].filter(Boolean);
|
|
4336
4482
|
}, ...(ngDevMode ? [{ debugName: "classes" }] : []));
|
|
4337
4483
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnExpansionPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4338
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnExpansionPanelComponent, isStandalone: true, selector: "tn-expansion-panel", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, elevation: { classPropertyName: "elevation", publicName: "elevation", isSignal: true, isRequired: false, transformFunction: null }, padding: { classPropertyName: "padding", publicName: "padding", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, background: { classPropertyName: "background", publicName: "background", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, titleStyle: { classPropertyName: "titleStyle", publicName: "titleStyle", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null }, toggleTestId: { classPropertyName: "toggleTestId", publicName: "toggleTestId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expandedChange: "expandedChange", toggleEvent: "toggleEvent" }, ngImport: i0, template: "<div tnTestIdType=\"expansion-panel\" [ngClass]=\"classes()\" [tnTestId]=\"testId()\">\n <button class=\"tn-expansion-panel__header\"\n tnTestIdType=\"button\"\n [disabled]=\"disabled()\"\n [attr.aria-expanded]=\"effectiveExpanded()\"\n [attr.aria-controls]=\"contentId\"\n [attr.aria-disabled]=\"disabled()\"\n [tnTestId]=\"toggleTestId()\"\n (click)=\"toggle()\">\n @if (title()) {\n <div class=\"tn-expansion-panel__title\">\n {{ title() }}\n </div>\n }\n <ng-content select=\"[slot=title]\" />\n\n <div class=\"tn-expansion-panel__indicator\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"m6 9 6 6 6-6\"/>\n </svg>\n </div>\n </button>\n\n <div class=\"tn-expansion-panel__content\"\n [
|
|
4484
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnExpansionPanelComponent, isStandalone: true, selector: "tn-expansion-panel", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, elevation: { classPropertyName: "elevation", publicName: "elevation", isSignal: true, isRequired: false, transformFunction: null }, padding: { classPropertyName: "padding", publicName: "padding", isSignal: true, isRequired: false, transformFunction: null }, bordered: { classPropertyName: "bordered", publicName: "bordered", isSignal: true, isRequired: false, transformFunction: null }, background: { classPropertyName: "background", publicName: "background", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, titleStyle: { classPropertyName: "titleStyle", publicName: "titleStyle", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null }, toggleTestId: { classPropertyName: "toggleTestId", publicName: "toggleTestId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expandedChange: "expandedChange", toggleEvent: "toggleEvent" }, ngImport: i0, template: "<div tnTestIdType=\"expansion-panel\" [ngClass]=\"classes()\" [tnTestId]=\"testId()\">\n <button class=\"tn-expansion-panel__header\"\n type=\"button\"\n tnTestIdType=\"button\"\n [disabled]=\"disabled()\"\n [attr.aria-expanded]=\"effectiveExpanded()\"\n [attr.aria-controls]=\"contentId\"\n [attr.aria-disabled]=\"disabled()\"\n [tnTestId]=\"toggleTestId()\"\n (click)=\"toggle()\">\n @if (title()) {\n <div class=\"tn-expansion-panel__title\">\n {{ title() }}\n </div>\n }\n <ng-content select=\"[slot=title]\" />\n\n <div class=\"tn-expansion-panel__indicator\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"m6 9 6 6 6-6\"/>\n </svg>\n </div>\n </button>\n\n <!-- `inert` (not aria-hidden) when collapsed: it removes the content from both\n the tab order and the a11y tree, so interactive children aren't keyboard-\n reachable while hidden. aria-hidden alone would leave them focusable, which\n is also an ARIA violation (aria-hidden must not contain focusable elements). -->\n <div class=\"tn-expansion-panel__content\"\n [class.tn-expansion-panel__content--collapsed]=\"!effectiveExpanded()\"\n [id]=\"contentId\"\n [attr.inert]=\"!effectiveExpanded() ? '' : null\">\n <div class=\"tn-expansion-panel__content-inner\">\n <ng-content />\n </div>\n </div>\n</div>\n", styles: [".tn-expansion-panel{border-radius:8px;transition:box-shadow .3s ease;overflow:hidden}.tn-expansion-panel--elevation-none{box-shadow:none}.tn-expansion-panel--elevation-low{box-shadow:0 1px 3px #0000001a}.tn-expansion-panel--elevation-medium{box-shadow:0 4px 6px #0000001a}.tn-expansion-panel--elevation-high{box-shadow:0 10px 15px #0000001a}.tn-expansion-panel--bordered{border:1px solid var(--tn-lines, #e5e7eb)}.tn-expansion-panel--background{background-color:var(--tn-bg2, #ffffff)}.tn-expansion-panel--disabled{opacity:.6;cursor:not-allowed}.tn-expansion-panel--disabled .tn-expansion-panel__header{cursor:not-allowed}.tn-expansion-panel--expanded .tn-expansion-panel__indicator svg{transform:rotate(180deg)}.tn-expansion-panel--padding-small .tn-expansion-panel__header{padding:12px 16px}.tn-expansion-panel--padding-small .tn-expansion-panel__content-inner{padding:0 16px 16px}.tn-expansion-panel--padding-medium .tn-expansion-panel__header{padding:16px 24px}.tn-expansion-panel--padding-medium .tn-expansion-panel__content-inner{padding:0 24px 24px}.tn-expansion-panel--padding-large .tn-expansion-panel__header{padding:24px 32px}.tn-expansion-panel--padding-large .tn-expansion-panel__content-inner{padding:0 32px 32px}.tn-expansion-panel--title-header .tn-expansion-panel__title{font-size:1.125rem;font-weight:600;color:var(--tn-fg1, #1f2937)}.tn-expansion-panel--title-header .tn-expansion-panel__indicator{color:var(--tn-fg1, #1f2937)}.tn-expansion-panel--title-body .tn-expansion-panel__title{font-size:1rem;font-weight:400;color:var(--tn-fg1, #1f2937)}.tn-expansion-panel--title-body .tn-expansion-panel__indicator{color:var(--tn-fg1, #1f2937)}.tn-expansion-panel--title-link .tn-expansion-panel__title{font-size:1rem;font-weight:400;color:var(--tn-primary, #3b82f6);text-decoration:none}.tn-expansion-panel--title-link .tn-expansion-panel__indicator{color:var(--tn-primary, #3b82f6)}.tn-expansion-panel--title-link .tn-expansion-panel__header:hover:not(:disabled) .tn-expansion-panel__title{text-decoration:underline}.tn-expansion-panel--title-link .tn-expansion-panel__header:focus .tn-expansion-panel__title{text-decoration:underline}.tn-expansion-panel__header{width:100%;background:none;border:none;color:var(--tn-fg1, #1f2937);display:flex;align-items:center;justify-content:space-between;cursor:pointer;font-family:inherit;text-align:left;transition:background-color .2s ease}.tn-expansion-panel--bordered .tn-expansion-panel__header{border-bottom:1px solid var(--tn-lines, #e5e7eb)}.tn-expansion-panel__header:hover:not(:disabled){background-color:var(--tn-alt-bg1, rgba(0, 0, 0, .05))}.tn-expansion-panel__header:focus{outline:2px solid var(--tn-primary, #3b82f6);outline-offset:-2px}.tn-expansion-panel__header:disabled{cursor:not-allowed}.tn-expansion-panel__title{margin:0;line-height:1.5;flex:1;transition:text-decoration .2s ease}.tn-expansion-panel__indicator{display:flex;align-items:center;justify-content:center;margin-left:16px;transition:transform .2s ease,color .2s ease}.tn-expansion-panel__indicator svg{transition:transform .2s ease}.tn-expansion-panel__content{display:grid;grid-template-rows:1fr;transition:grid-template-rows .3s cubic-bezier(.4,0,.2,1)}.tn-expansion-panel__content--collapsed{grid-template-rows:0fr}.tn-expansion-panel__content-inner{min-height:0;overflow:hidden}@media(prefers-reduced-motion:reduce){.tn-expansion-panel,.tn-expansion-panel__header,.tn-expansion-panel__title,.tn-expansion-panel__indicator,.tn-expansion-panel__indicator svg,.tn-expansion-panel__content{transition:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: TnTestIdDirective, selector: "[tnTestId]", inputs: ["tnTestId", "tnTestIdType"] }] });
|
|
4339
4485
|
}
|
|
4340
4486
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnExpansionPanelComponent, decorators: [{
|
|
4341
4487
|
type: Component,
|
|
4342
|
-
args: [{ selector: 'tn-expansion-panel', standalone: true, imports: [CommonModule, TnTestIdDirective],
|
|
4488
|
+
args: [{ selector: 'tn-expansion-panel', standalone: true, imports: [CommonModule, TnTestIdDirective], template: "<div tnTestIdType=\"expansion-panel\" [ngClass]=\"classes()\" [tnTestId]=\"testId()\">\n <button class=\"tn-expansion-panel__header\"\n type=\"button\"\n tnTestIdType=\"button\"\n [disabled]=\"disabled()\"\n [attr.aria-expanded]=\"effectiveExpanded()\"\n [attr.aria-controls]=\"contentId\"\n [attr.aria-disabled]=\"disabled()\"\n [tnTestId]=\"toggleTestId()\"\n (click)=\"toggle()\">\n @if (title()) {\n <div class=\"tn-expansion-panel__title\">\n {{ title() }}\n </div>\n }\n <ng-content select=\"[slot=title]\" />\n\n <div class=\"tn-expansion-panel__indicator\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <path d=\"m6 9 6 6 6-6\"/>\n </svg>\n </div>\n </button>\n\n <!-- `inert` (not aria-hidden) when collapsed: it removes the content from both\n the tab order and the a11y tree, so interactive children aren't keyboard-\n reachable while hidden. aria-hidden alone would leave them focusable, which\n is also an ARIA violation (aria-hidden must not contain focusable elements). -->\n <div class=\"tn-expansion-panel__content\"\n [class.tn-expansion-panel__content--collapsed]=\"!effectiveExpanded()\"\n [id]=\"contentId\"\n [attr.inert]=\"!effectiveExpanded() ? '' : null\">\n <div class=\"tn-expansion-panel__content-inner\">\n <ng-content />\n </div>\n </div>\n</div>\n", styles: [".tn-expansion-panel{border-radius:8px;transition:box-shadow .3s ease;overflow:hidden}.tn-expansion-panel--elevation-none{box-shadow:none}.tn-expansion-panel--elevation-low{box-shadow:0 1px 3px #0000001a}.tn-expansion-panel--elevation-medium{box-shadow:0 4px 6px #0000001a}.tn-expansion-panel--elevation-high{box-shadow:0 10px 15px #0000001a}.tn-expansion-panel--bordered{border:1px solid var(--tn-lines, #e5e7eb)}.tn-expansion-panel--background{background-color:var(--tn-bg2, #ffffff)}.tn-expansion-panel--disabled{opacity:.6;cursor:not-allowed}.tn-expansion-panel--disabled .tn-expansion-panel__header{cursor:not-allowed}.tn-expansion-panel--expanded .tn-expansion-panel__indicator svg{transform:rotate(180deg)}.tn-expansion-panel--padding-small .tn-expansion-panel__header{padding:12px 16px}.tn-expansion-panel--padding-small .tn-expansion-panel__content-inner{padding:0 16px 16px}.tn-expansion-panel--padding-medium .tn-expansion-panel__header{padding:16px 24px}.tn-expansion-panel--padding-medium .tn-expansion-panel__content-inner{padding:0 24px 24px}.tn-expansion-panel--padding-large .tn-expansion-panel__header{padding:24px 32px}.tn-expansion-panel--padding-large .tn-expansion-panel__content-inner{padding:0 32px 32px}.tn-expansion-panel--title-header .tn-expansion-panel__title{font-size:1.125rem;font-weight:600;color:var(--tn-fg1, #1f2937)}.tn-expansion-panel--title-header .tn-expansion-panel__indicator{color:var(--tn-fg1, #1f2937)}.tn-expansion-panel--title-body .tn-expansion-panel__title{font-size:1rem;font-weight:400;color:var(--tn-fg1, #1f2937)}.tn-expansion-panel--title-body .tn-expansion-panel__indicator{color:var(--tn-fg1, #1f2937)}.tn-expansion-panel--title-link .tn-expansion-panel__title{font-size:1rem;font-weight:400;color:var(--tn-primary, #3b82f6);text-decoration:none}.tn-expansion-panel--title-link .tn-expansion-panel__indicator{color:var(--tn-primary, #3b82f6)}.tn-expansion-panel--title-link .tn-expansion-panel__header:hover:not(:disabled) .tn-expansion-panel__title{text-decoration:underline}.tn-expansion-panel--title-link .tn-expansion-panel__header:focus .tn-expansion-panel__title{text-decoration:underline}.tn-expansion-panel__header{width:100%;background:none;border:none;color:var(--tn-fg1, #1f2937);display:flex;align-items:center;justify-content:space-between;cursor:pointer;font-family:inherit;text-align:left;transition:background-color .2s ease}.tn-expansion-panel--bordered .tn-expansion-panel__header{border-bottom:1px solid var(--tn-lines, #e5e7eb)}.tn-expansion-panel__header:hover:not(:disabled){background-color:var(--tn-alt-bg1, rgba(0, 0, 0, .05))}.tn-expansion-panel__header:focus{outline:2px solid var(--tn-primary, #3b82f6);outline-offset:-2px}.tn-expansion-panel__header:disabled{cursor:not-allowed}.tn-expansion-panel__title{margin:0;line-height:1.5;flex:1;transition:text-decoration .2s ease}.tn-expansion-panel__indicator{display:flex;align-items:center;justify-content:center;margin-left:16px;transition:transform .2s ease,color .2s ease}.tn-expansion-panel__indicator svg{transition:transform .2s ease}.tn-expansion-panel__content{display:grid;grid-template-rows:1fr;transition:grid-template-rows .3s cubic-bezier(.4,0,.2,1)}.tn-expansion-panel__content--collapsed{grid-template-rows:0fr}.tn-expansion-panel__content-inner{min-height:0;overflow:hidden}@media(prefers-reduced-motion:reduce){.tn-expansion-panel,.tn-expansion-panel__header,.tn-expansion-panel__title,.tn-expansion-panel__indicator,.tn-expansion-panel__indicator svg,.tn-expansion-panel__content{transition:none}}\n"] }]
|
|
4343
4489
|
}], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], elevation: [{ type: i0.Input, args: [{ isSignal: true, alias: "elevation", required: false }] }], padding: [{ type: i0.Input, args: [{ isSignal: true, alias: "padding", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], background: [{ type: i0.Input, args: [{ isSignal: true, alias: "background", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], titleStyle: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleStyle", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], toggleTestId: [{ type: i0.Input, args: [{ isSignal: true, alias: "toggleTestId", required: false }] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }], toggleEvent: [{ type: i0.Output, args: ["toggleEvent"] }] } });
|
|
4344
4490
|
|
|
4345
4491
|
/**
|
|
@@ -7490,81 +7636,6 @@ class TnSelectHarness extends ComponentHarness {
|
|
|
7490
7636
|
}
|
|
7491
7637
|
}
|
|
7492
7638
|
|
|
7493
|
-
/**
|
|
7494
|
-
* Marks an icon name for inclusion in the TrueNAS UI sprite generation.
|
|
7495
|
-
*
|
|
7496
|
-
* This function serves two purposes:
|
|
7497
|
-
* 1. At runtime: Applies library-specific prefixes (e.g., mdi-, app-)
|
|
7498
|
-
* 2. At build time: Marker for the scanner to detect icons for sprite inclusion
|
|
7499
|
-
*
|
|
7500
|
-
* Use this when icon names are computed dynamically or come from variables,
|
|
7501
|
-
* to ensure they're included in the sprite at build time.
|
|
7502
|
-
*
|
|
7503
|
-
* @example
|
|
7504
|
-
* // Static icon name - automatically detected from template
|
|
7505
|
-
* <tn-icon name="folder"></tn-icon>
|
|
7506
|
-
*
|
|
7507
|
-
* @example
|
|
7508
|
-
* // Dynamic MDI icon
|
|
7509
|
-
* const iconName = condition ? tnIconMarker("pencil", "mdi") : tnIconMarker("delete", "mdi");
|
|
7510
|
-
* <tn-icon [name]="iconName"></tn-icon>
|
|
7511
|
-
*
|
|
7512
|
-
* @example
|
|
7513
|
-
* // Dynamic custom icon (consumer's own icon)
|
|
7514
|
-
* const logo = tnIconMarker("your-logo-name", "custom");
|
|
7515
|
-
* <tn-icon [name]="logo"></tn-icon>
|
|
7516
|
-
*
|
|
7517
|
-
* @example
|
|
7518
|
-
* // Array of dynamic icons
|
|
7519
|
-
* const actions = [
|
|
7520
|
-
* { name: "Save", icon: tnIconMarker("content-save", "mdi") },
|
|
7521
|
-
* { name: "Cancel", icon: tnIconMarker("close", "mdi") }
|
|
7522
|
-
* ];
|
|
7523
|
-
*
|
|
7524
|
-
* @param iconName - The icon name to mark for sprite inclusion
|
|
7525
|
-
* @param library - Optional library type: 'mdi', 'material', or 'custom'
|
|
7526
|
-
* @returns The icon name with appropriate prefix applied
|
|
7527
|
-
* @public
|
|
7528
|
-
*/
|
|
7529
|
-
function tnIconMarker(iconName, library) {
|
|
7530
|
-
// Apply library-specific prefixes
|
|
7531
|
-
if (library === 'mdi' && !iconName.startsWith('mdi-')) {
|
|
7532
|
-
return `mdi-${iconName}`;
|
|
7533
|
-
}
|
|
7534
|
-
if (library === 'custom' && !iconName.startsWith('app-')) {
|
|
7535
|
-
return `app-${iconName}`;
|
|
7536
|
-
}
|
|
7537
|
-
if (library === 'material' && !iconName.startsWith('mat-')) {
|
|
7538
|
-
return `mat-${iconName}`;
|
|
7539
|
-
}
|
|
7540
|
-
return iconName;
|
|
7541
|
-
}
|
|
7542
|
-
/**
|
|
7543
|
-
* INTERNAL LIBRARY USE ONLY
|
|
7544
|
-
*
|
|
7545
|
-
* Marks an icon name for inclusion in the sprite generation with library namespace.
|
|
7546
|
-
* This function MUST be used by library component code for custom icons.
|
|
7547
|
-
*
|
|
7548
|
-
* The TypeScript type enforces that the icon name starts with 'tn-' prefix,
|
|
7549
|
-
* which reserves this namespace exclusively for library-provided custom icons.
|
|
7550
|
-
*
|
|
7551
|
-
* @example
|
|
7552
|
-
* ```typescript
|
|
7553
|
-
* // ✅ Correct - Library component code
|
|
7554
|
-
* const icon = libIconMarker('tn-dataset');
|
|
7555
|
-
*
|
|
7556
|
-
* // ❌ Wrong - Will cause TypeScript error
|
|
7557
|
-
* const icon = libIconMarker('dataset');
|
|
7558
|
-
* ```
|
|
7559
|
-
*
|
|
7560
|
-
* @param iconName - The icon name with 'tn-' prefix (enforced by TypeScript)
|
|
7561
|
-
* @returns The same icon name (identity function)
|
|
7562
|
-
* @internal
|
|
7563
|
-
*/
|
|
7564
|
-
function libIconMarker(iconName) {
|
|
7565
|
-
return iconName;
|
|
7566
|
-
}
|
|
7567
|
-
|
|
7568
7639
|
/// <reference types="jest" />
|
|
7569
7640
|
/**
|
|
7570
7641
|
* Creates default mock implementation of TnSpriteLoaderService.
|
|
@@ -12975,6 +13046,22 @@ let nextUniqueId = 0;
|
|
|
12975
13046
|
class TnDialogShellComponent {
|
|
12976
13047
|
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
12977
13048
|
showFullscreenButton = input(false, ...(ngDevMode ? [{ debugName: "showFullscreenButton" }] : []));
|
|
13049
|
+
/**
|
|
13050
|
+
* Show the header close (X) button. Disable for dialogs that must not be
|
|
13051
|
+
* dismissed from the chrome — e.g. a running job that can only be minimized.
|
|
13052
|
+
*/
|
|
13053
|
+
showCloseButton = input(true, ...(ngDevMode ? [{ debugName: "showCloseButton" }] : []));
|
|
13054
|
+
/**
|
|
13055
|
+
* Hide the content section. Use when the body is projected through an
|
|
13056
|
+
* always-present wrapper whose contents are conditional, so the section is
|
|
13057
|
+
* never truly `:empty` (consumers cannot project from inside an `@if`, see
|
|
13058
|
+
* the dialog docs). An empty section with no wrapper is hidden automatically
|
|
13059
|
+
* via the `:empty` rule in the theme, so this input is only needed for the
|
|
13060
|
+
* wrapper case.
|
|
13061
|
+
*/
|
|
13062
|
+
hideContent = input(false, ...(ngDevMode ? [{ debugName: "hideContent" }] : []));
|
|
13063
|
+
/** Hide the actions footer. Same wrapper-case rationale as {@link hideContent}. */
|
|
13064
|
+
hideActions = input(false, ...(ngDevMode ? [{ debugName: "hideActions" }] : []));
|
|
12978
13065
|
/**
|
|
12979
13066
|
* Optional semantic base that scopes the shell's chrome buttons. The close
|
|
12980
13067
|
* and fullscreen buttons emit `button-close` / `button-fullscreen` by default,
|
|
@@ -13081,20 +13168,20 @@ class TnDialogShellComponent {
|
|
|
13081
13168
|
}
|
|
13082
13169
|
}
|
|
13083
13170
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnDialogShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13084
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnDialogShellComponent, isStandalone: true, selector: "tn-dialog-shell", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, showFullscreenButton: { classPropertyName: "showFullscreenButton", publicName: "showFullscreenButton", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "tn-dialog-shell" }, ngImport: i0, template: "<header class=\"tn-dialog__header\">\n <h2 class=\"tn-dialog__title\" [id]=\"titleId\">{{ title() }}</h2>\n @if (showFullscreenButton()) {\n <button\n type=\"button\"\n class=\"tn-dialog__fullscreen\"\n tnTestIdType=\"button\"\n [tnTestId]=\"fullscreenTestId()\"\n [attr.aria-label]=\"isFullscreen() ? 'Exit fullscreen' : 'Enter fullscreen'\"\n (click)=\"toggleFullscreen()\">\n <span class=\"tn-dialog__fullscreen-icon\" aria-hidden=\"true\">{{ isFullscreen() ? '\u2913' : '\u2922' }}</span>\n </button>\n }\n <button type=\"button\" class=\"tn-dialog__close\" aria-label=\"Close dialog\" tnTestIdType=\"button\" [tnTestId]=\"closeTestId()\" (click)=\"close()\">\n
|
|
13171
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnDialogShellComponent, isStandalone: true, selector: "tn-dialog-shell", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, showFullscreenButton: { classPropertyName: "showFullscreenButton", publicName: "showFullscreenButton", isSignal: true, isRequired: false, transformFunction: null }, showCloseButton: { classPropertyName: "showCloseButton", publicName: "showCloseButton", isSignal: true, isRequired: false, transformFunction: null }, hideContent: { classPropertyName: "hideContent", publicName: "hideContent", isSignal: true, isRequired: false, transformFunction: null }, hideActions: { classPropertyName: "hideActions", publicName: "hideActions", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "tn-dialog-shell" }, ngImport: i0, template: "<header class=\"tn-dialog__header\">\n <h2 class=\"tn-dialog__title\" [id]=\"titleId\">{{ title() }}</h2>\n @if (showFullscreenButton()) {\n <button\n type=\"button\"\n class=\"tn-dialog__fullscreen\"\n tnTestIdType=\"button\"\n [tnTestId]=\"fullscreenTestId()\"\n [attr.aria-label]=\"isFullscreen() ? 'Exit fullscreen' : 'Enter fullscreen'\"\n (click)=\"toggleFullscreen()\">\n <span class=\"tn-dialog__fullscreen-icon\" aria-hidden=\"true\">{{ isFullscreen() ? '\u2913' : '\u2922' }}</span>\n </button>\n }\n @if (showCloseButton()) {\n <button type=\"button\" class=\"tn-dialog__close\" aria-label=\"Close dialog\" tnTestIdType=\"button\" [tnTestId]=\"closeTestId()\" (click)=\"close()\">\n <span class=\"tn-dialog__close-icon\" aria-hidden=\"true\">\u2715</span>\n </button>\n }\n</header>\n\n<section class=\"tn-dialog__content\" cdkDialogContent [class.tn-dialog__content--hidden]=\"hideContent()\">\n <ng-content />\n</section>\n\n<footer class=\"tn-dialog__actions\" cdkDialogActions [class.tn-dialog__actions--hidden]=\"hideActions()\">\n <ng-content select=\"[tnDialogAction]\" />\n</footer>\n", dependencies: [{ kind: "directive", type: TnTestIdDirective, selector: "[tnTestId]", inputs: ["tnTestId", "tnTestIdType"] }] });
|
|
13085
13172
|
}
|
|
13086
13173
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnDialogShellComponent, decorators: [{
|
|
13087
13174
|
type: Component,
|
|
13088
13175
|
args: [{ selector: 'tn-dialog-shell', standalone: true, imports: [TnTestIdDirective], host: {
|
|
13089
13176
|
'class': 'tn-dialog-shell'
|
|
13090
|
-
}, template: "<header class=\"tn-dialog__header\">\n <h2 class=\"tn-dialog__title\" [id]=\"titleId\">{{ title() }}</h2>\n @if (showFullscreenButton()) {\n <button\n type=\"button\"\n class=\"tn-dialog__fullscreen\"\n tnTestIdType=\"button\"\n [tnTestId]=\"fullscreenTestId()\"\n [attr.aria-label]=\"isFullscreen() ? 'Exit fullscreen' : 'Enter fullscreen'\"\n (click)=\"toggleFullscreen()\">\n <span class=\"tn-dialog__fullscreen-icon\" aria-hidden=\"true\">{{ isFullscreen() ? '\u2913' : '\u2922' }}</span>\n </button>\n }\n <button type=\"button\" class=\"tn-dialog__close\" aria-label=\"Close dialog\" tnTestIdType=\"button\" [tnTestId]=\"closeTestId()\" (click)=\"close()\">\n
|
|
13091
|
-
}], ctorParameters: () => [], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], showFullscreenButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFullscreenButton", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }] } });
|
|
13177
|
+
}, template: "<header class=\"tn-dialog__header\">\n <h2 class=\"tn-dialog__title\" [id]=\"titleId\">{{ title() }}</h2>\n @if (showFullscreenButton()) {\n <button\n type=\"button\"\n class=\"tn-dialog__fullscreen\"\n tnTestIdType=\"button\"\n [tnTestId]=\"fullscreenTestId()\"\n [attr.aria-label]=\"isFullscreen() ? 'Exit fullscreen' : 'Enter fullscreen'\"\n (click)=\"toggleFullscreen()\">\n <span class=\"tn-dialog__fullscreen-icon\" aria-hidden=\"true\">{{ isFullscreen() ? '\u2913' : '\u2922' }}</span>\n </button>\n }\n @if (showCloseButton()) {\n <button type=\"button\" class=\"tn-dialog__close\" aria-label=\"Close dialog\" tnTestIdType=\"button\" [tnTestId]=\"closeTestId()\" (click)=\"close()\">\n <span class=\"tn-dialog__close-icon\" aria-hidden=\"true\">\u2715</span>\n </button>\n }\n</header>\n\n<section class=\"tn-dialog__content\" cdkDialogContent [class.tn-dialog__content--hidden]=\"hideContent()\">\n <ng-content />\n</section>\n\n<footer class=\"tn-dialog__actions\" cdkDialogActions [class.tn-dialog__actions--hidden]=\"hideActions()\">\n <ng-content select=\"[tnDialogAction]\" />\n</footer>\n" }]
|
|
13178
|
+
}], ctorParameters: () => [], propDecorators: { title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], showFullscreenButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFullscreenButton", required: false }] }], showCloseButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showCloseButton", required: false }] }], hideContent: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideContent", required: false }] }], hideActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideActions", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }] } });
|
|
13092
13179
|
|
|
13093
13180
|
class TnConfirmDialogComponent {
|
|
13094
13181
|
ref = inject((DialogRef));
|
|
13095
13182
|
data = inject(DIALOG_DATA);
|
|
13096
13183
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnConfirmDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13097
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.0", type: TnConfirmDialogComponent, isStandalone: true, selector: "tn-confirm-dialog", host: { properties: { "class.tn-dialog--destructive": "data.destructive" }, classAttribute: "tn-dialog-shell" }, ngImport: i0, template: "<tn-dialog-shell [title]=\"data.title\">\n <p style=\"margin: 0;\">{{ data.message }}</p>\n <div tnDialogAction>\n <tn-button\n type=\"button\"\n variant=\"outline\"\n [label]=\"data.cancelText || 'Cancel'\"\n [testId]=\"data.cancelTestId || 'cancel'\"\n (click)=\"ref.close(false)\" />\n <tn-button\n type=\"button\"\n [color]=\"data.destructive ? 'warn' : 'primary'\"\n [label]=\"data.confirmText || 'OK'\"\n [testId]=\"data.confirmTestId || 'confirm'\"\n (click)=\"ref.close(true)\" />\n </div>\n</tn-dialog-shell>\n", dependencies: [{ kind: "component", type: TnDialogShellComponent, selector: "tn-dialog-shell", inputs: ["title", "showFullscreenButton", "testId"] }, { kind: "component", type: TnButtonComponent, selector: "tn-button", inputs: ["primary", "color", "variant", "backgroundColor", "label", "disabled", "type", "testId", "href", "routerLink", "queryParams", "fragment", "target", "rel", "ariaLabel"], outputs: ["onClick"] }] });
|
|
13184
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.0", type: TnConfirmDialogComponent, isStandalone: true, selector: "tn-confirm-dialog", host: { properties: { "class.tn-dialog--destructive": "data.destructive" }, classAttribute: "tn-dialog-shell" }, ngImport: i0, template: "<tn-dialog-shell [title]=\"data.title\">\n <p style=\"margin: 0;\">{{ data.message }}</p>\n <div tnDialogAction>\n <tn-button\n type=\"button\"\n variant=\"outline\"\n [label]=\"data.cancelText || 'Cancel'\"\n [testId]=\"data.cancelTestId || 'cancel'\"\n (click)=\"ref.close(false)\" />\n <tn-button\n type=\"button\"\n [color]=\"data.destructive ? 'warn' : 'primary'\"\n [label]=\"data.confirmText || 'OK'\"\n [testId]=\"data.confirmTestId || 'confirm'\"\n (click)=\"ref.close(true)\" />\n </div>\n</tn-dialog-shell>\n", dependencies: [{ kind: "component", type: TnDialogShellComponent, selector: "tn-dialog-shell", inputs: ["title", "showFullscreenButton", "showCloseButton", "hideContent", "hideActions", "testId"] }, { kind: "component", type: TnButtonComponent, selector: "tn-button", inputs: ["primary", "color", "variant", "backgroundColor", "label", "disabled", "type", "testId", "href", "routerLink", "queryParams", "fragment", "target", "rel", "ariaLabel"], outputs: ["onClick"] }] });
|
|
13098
13185
|
}
|
|
13099
13186
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnConfirmDialogComponent, decorators: [{
|
|
13100
13187
|
type: Component,
|