@truenas/ui-components 0.3.16 → 0.3.17
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.
|
@@ -15737,10 +15737,12 @@ class TnStepComponent {
|
|
|
15737
15737
|
optional = input(false, ...(ngDevMode ? [{ debugName: "optional" }] : []));
|
|
15738
15738
|
completed = input(false, ...(ngDevMode ? [{ debugName: "completed" }] : []));
|
|
15739
15739
|
hasError = input(false, ...(ngDevMode ? [{ debugName: "hasError" }] : []));
|
|
15740
|
+
/** Message shown beneath the step label while the step is in an error state. */
|
|
15741
|
+
errorMessage = input(undefined, ...(ngDevMode ? [{ debugName: "errorMessage" }] : []));
|
|
15740
15742
|
data = input(null, ...(ngDevMode ? [{ debugName: "data" }] : []));
|
|
15741
15743
|
content = viewChild.required('content');
|
|
15742
15744
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnStepComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
15743
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.1.0", type: TnStepComponent, isStandalone: true, selector: "tn-step", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, optional: { classPropertyName: "optional", publicName: "optional", isSignal: true, isRequired: false, transformFunction: null }, completed: { classPropertyName: "completed", publicName: "completed", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
15745
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.1.0", type: TnStepComponent, isStandalone: true, selector: "tn-step", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, optional: { classPropertyName: "optional", publicName: "optional", isSignal: true, isRequired: false, transformFunction: null }, completed: { classPropertyName: "completed", publicName: "completed", isSignal: true, isRequired: false, transformFunction: null }, hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "content", first: true, predicate: ["content"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
15744
15746
|
<ng-template #content>
|
|
15745
15747
|
<ng-content />
|
|
15746
15748
|
</ng-template>
|
|
@@ -15757,7 +15759,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
15757
15759
|
`,
|
|
15758
15760
|
standalone: true
|
|
15759
15761
|
}]
|
|
15760
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], optional: [{ type: i0.Input, args: [{ isSignal: true, alias: "optional", required: false }] }], completed: [{ type: i0.Input, args: [{ isSignal: true, alias: "completed", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], content: [{ type: i0.ViewChild, args: ['content', { isSignal: true }] }] } });
|
|
15762
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], optional: [{ type: i0.Input, args: [{ isSignal: true, alias: "optional", required: false }] }], completed: [{ type: i0.Input, args: [{ isSignal: true, alias: "completed", required: false }] }], hasError: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasError", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], content: [{ type: i0.ViewChild, args: ['content', { isSignal: true }] }] } });
|
|
15761
15763
|
|
|
15762
15764
|
class TnStepperComponent {
|
|
15763
15765
|
orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : []));
|
|
@@ -15771,8 +15773,15 @@ class TnStepperComponent {
|
|
|
15771
15773
|
selectionChange = output();
|
|
15772
15774
|
completed = output();
|
|
15773
15775
|
steps = contentChildren(TnStepComponent, { ...(ngDevMode ? { debugName: "steps" } : {}), descendants: true });
|
|
15774
|
-
|
|
15776
|
+
// Highest step index the user has navigated to. Used to reveal the "edit" (pencil)
|
|
15777
|
+
// affordance only on steps that have actually been visited — a step that is valid by
|
|
15778
|
+
// default but never reached stays a plain number.
|
|
15779
|
+
maxReachedIndex = signal(0, ...(ngDevMode ? [{ debugName: "maxReachedIndex" }] : []));
|
|
15775
15780
|
constructor() {
|
|
15781
|
+
effect(() => {
|
|
15782
|
+
const index = this.selectedIndex();
|
|
15783
|
+
this.maxReachedIndex.update((max) => Math.max(max, index));
|
|
15784
|
+
});
|
|
15776
15785
|
// Effect to check if all steps are completed
|
|
15777
15786
|
effect(() => {
|
|
15778
15787
|
// Trigger on any step completion change
|
|
@@ -15783,8 +15792,8 @@ class TnStepperComponent {
|
|
|
15783
15792
|
}
|
|
15784
15793
|
});
|
|
15785
15794
|
}
|
|
15786
|
-
onWindowResize(
|
|
15787
|
-
this.
|
|
15795
|
+
onWindowResize() {
|
|
15796
|
+
this.isWideScreen.set(window.innerWidth > 768);
|
|
15788
15797
|
}
|
|
15789
15798
|
_getStepData() {
|
|
15790
15799
|
return this.steps().map(step => ({
|
|
@@ -15793,10 +15802,33 @@ class TnStepperComponent {
|
|
|
15793
15802
|
data: step.data()
|
|
15794
15803
|
}));
|
|
15795
15804
|
}
|
|
15796
|
-
|
|
15797
|
-
|
|
15798
|
-
|
|
15799
|
-
|
|
15805
|
+
// Tracks whether the viewport is wide enough for the horizontal layout. A signal
|
|
15806
|
+
// (not a computed over `window.innerWidth`, which is non-reactive and would freeze on
|
|
15807
|
+
// first read) so `onWindowResize` can `.set()` it and `auto` orientation re-evaluates.
|
|
15808
|
+
isWideScreen = signal(window.innerWidth > 768, ...(ngDevMode ? [{ debugName: "isWideScreen" }] : []));
|
|
15809
|
+
// Vertical mode lays the active step's content out inline beneath its header
|
|
15810
|
+
// (mat-vertical-stepper style), so it fits narrow containers such as side panels.
|
|
15811
|
+
isVertical = computed(() => {
|
|
15812
|
+
return this.orientation() === 'vertical' || (this.orientation() === 'auto' && !this.isWideScreen());
|
|
15813
|
+
}, ...(ngDevMode ? [{ debugName: "isVertical" }] : []));
|
|
15814
|
+
// Per-index "editable" flags. A step shows the "edit" (pencil) icon once it has been
|
|
15815
|
+
// visited and is valid (completed) but isn't the current step — signalling the user can
|
|
15816
|
+
// go back and change it. Computed (not a per-call method) so it's evaluated once per
|
|
15817
|
+
// change-detection cycle and cheaply indexed in the template, even as step counts grow.
|
|
15818
|
+
stepEditable = computed(() => {
|
|
15819
|
+
const max = this.maxReachedIndex();
|
|
15820
|
+
const current = this.selectedIndex();
|
|
15821
|
+
return this.steps().map((step, index) => !!step.completed() && index <= max && index !== current);
|
|
15822
|
+
}, ...(ngDevMode ? [{ debugName: "stepEditable" }] : []));
|
|
15823
|
+
// Per-index "gated" flags for linear mode: a step is gated (not yet selectable) while
|
|
15824
|
+
// any prior step is incomplete. Memoized so the header's aria-disabled / tabindex
|
|
15825
|
+
// bindings don't re-run canSelectStep() for every step on each change-detection cycle.
|
|
15826
|
+
stepGated = computed(() => {
|
|
15827
|
+
if (!this.linear()) {
|
|
15828
|
+
return this.steps().map(() => false);
|
|
15829
|
+
}
|
|
15830
|
+
return this.steps().map((_step, index) => !this.canSelectStep(index));
|
|
15831
|
+
}, ...(ngDevMode ? [{ debugName: "stepGated" }] : []));
|
|
15800
15832
|
selectStep(index) {
|
|
15801
15833
|
if (!this.linear() || this.canSelectStep(index)) {
|
|
15802
15834
|
const previousIndex = this.selectedIndex();
|
|
@@ -15835,7 +15867,7 @@ class TnStepperComponent {
|
|
|
15835
15867
|
return index;
|
|
15836
15868
|
}
|
|
15837
15869
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnStepperComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
15838
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnStepperComponent, isStandalone: true, selector: "tn-stepper", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, linear: { classPropertyName: "linear", publicName: "linear", isSignal: true, isRequired: false, transformFunction: null }, selectedIndex: { classPropertyName: "selectedIndex", publicName: "selectedIndex", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedIndex: "selectedIndexChange", selectionChange: "selectionChange", completed: "completed" }, host: { listeners: { "window:resize": "onWindowResize($event)" } }, queries: [{ propertyName: "steps", predicate: TnStepComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"tn-stepper\"\n tnTestIdType=\"stepper\"\n [class.tn-stepper--horizontal]=\"orientation() === 'horizontal' || (orientation() === 'auto' && isWideScreen())\"\n [class.tn-stepper--vertical]=\"orientation() === 'vertical' || (orientation() === 'auto' && !isWideScreen())\"\n [tnTestId]=\"testId()\">\n\n <!-- Step Headers -->\n <div class=\"tn-stepper__header\">\n @for (step of steps(); track $index; let i = $index) {\n <div class=\"tn-stepper__step-header\"\n tabindex=\"0\"\n role=\"button\"\n [class.tn-stepper__step-header--active]=\"selectedIndex() === i\"\n [class.tn-stepper__step-header--completed]=\"step.completed()\"\n [class.tn-stepper__step-header--error]=\"step.hasError()\"\n [class.tn-stepper__step-header--optional]=\"step.optional()\"\n (click)=\"selectStep(i)\"\n (keydown.enter)=\"selectStep(i)\"\n (keydown.space)=\"selectStep(i)\">\n\n <!-- Step Number/Icon -->\n <div class=\"tn-stepper__step-indicator\">\n @if (step.completed() && !step.hasError()) {\n <span class=\"tn-stepper__step-check\">\u2713</span>\n }\n @if (step.hasError()) {\n <span class=\"tn-stepper__step-error\">!</span>\n }\n @if (!step.completed() && !step.hasError()) {\n @if (step.icon()) {\n <span class=\"tn-stepper__step-icon\">{{ step.icon() }}</span>\n } @else {\n <span class=\"tn-stepper__step-number\">{{ i + 1 }}</span>\n }\n }\n </div>\n\n <!-- Step Label -->\n <div class=\"tn-stepper__step-label\">\n <div class=\"tn-stepper__step-title\" [innerHTML]=\"step.label() | tnLabelMarkup\"></div>\n @if (step.optional()) {\n <span class=\"tn-stepper__step-subtitle\">Optional</span>\n }\n </div>\n </div>\n\n <!-- Connector Line (except for last step) -->\n @if (i < steps().length - 1) {\n <div class=\"tn-stepper__connector\"></div>\n }\n }\n </div>\n\n <!-- Step Content -->\n <div class=\"tn-stepper__content\">\n @for (step of steps(); track $index; let i = $index) {\n @if (selectedIndex() === i) {\n <div class=\"tn-stepper__step-content\"\n [@stepTransition]=\"selectedIndex()\">\n <ng-container *ngTemplateOutlet=\"step.content()\" />\n </div>\n }\n }\n </div>\n</div>", styles: [".tn-stepper{display:flex;font-family:inherit;--step-diameter: 48px;--step-diameter-sm: 32px;--step-padding: 12px}.tn-stepper--horizontal{flex-direction:column}.tn-stepper--horizontal .tn-stepper__header{display:flex;justify-content:center;margin-bottom:32px;padding:0 16px}.tn-stepper--horizontal .tn-stepper__step-header{display:flex;flex-direction:column;align-items:center;text-align:center;cursor:pointer;transition:all .2s ease-in-out}.tn-stepper--horizontal .tn-stepper__step-header:not(.tn-stepper__step-header--active):hover .tn-stepper__step-indicator{transform:scale(.95)}.tn-stepper--horizontal .tn-stepper__connector{flex:1;height:2px;background:var(--tn-lines, #e5e7eb);margin:0 16px;position:relative;top:calc(var(--step-diameter) / 2)}.tn-stepper--vertical{flex-direction:row}.tn-stepper--vertical .tn-stepper__header{display:flex;flex-direction:column;width:280px;padding:16px;border-right:1px solid var(--tn-lines, #e5e7eb)}.tn-stepper--vertical .tn-stepper__step-header{display:flex;flex-direction:row;align-items:center;text-align:left;cursor:pointer;transition:all .2s ease-in-out;padding:var(--step-padding);border-radius:8px;margin-bottom:8px}.tn-stepper--vertical .tn-stepper__step-header:not(.tn-stepper__step-header--active):hover .tn-stepper__step-indicator{transform:scale(.95)}.tn-stepper--vertical .tn-stepper__step-header .tn-stepper__step-label{margin-left:12px;margin-top:0}.tn-stepper--vertical .tn-stepper__connector{width:2px;height:24px;background:var(--tn-lines, #e5e7eb);position:relative;left:calc(var(--step-diameter) / 2 + var(--step-padding));margin-bottom:8px}.tn-stepper--vertical .tn-stepper__content{flex:1;padding:16px}.tn-stepper__step-indicator{display:flex;align-items:center;justify-content:center;width:var(--step-diameter);height:var(--step-diameter);border-radius:50%;background:var(--tn-alt-bg1, #f8f9fa);color:var(--tn-alt-fg1, #495057);font-weight:400;font-size:14px;transition:all .2s ease-in-out;position:relative;transform:scale(.65)}.tn-stepper__step-number{font-weight:400}.tn-stepper__step-label{margin-top:8px}.tn-stepper__step-title ::ng-deep code{font-family:var(--tn-font-family-monospace, monospace);font-size:.875em;background:var(--tn-bg2, #f5f5f5);border:1px solid var(--tn-lines, #ccc);border-radius:4px;padding:.125em .45em}.tn-stepper__step-title{display:block;font-weight:400;font-size:14px;color:var(--tn-fg1, #000000);line-height:1.2}.tn-stepper__step-subtitle{display:block;font-size:12px;color:var(--tn-fg2, #6c757d);margin-top:2px}.tn-stepper__step-header--active .tn-stepper__step-indicator{background:var(--tn-primary, #007bff);color:var(--tn-primary-txt, #ffffff);transform:scale(1)}.tn-stepper__step-header--active .tn-stepper__step-title{color:var(--tn-fg2, #6c757d);font-weight:600}.tn-stepper__step-header--completed .tn-stepper__step-indicator{background:var(--tn-green, #28a745);color:#fff}.tn-stepper__step-header--completed .tn-stepper__step-check{font-size:1rem;font-weight:700}.tn-stepper__step-header--error .tn-stepper__step-indicator{background:var(--tn-red, #dc3545);color:#fff}.tn-stepper__step-header--error .tn-stepper__step-error{font-size:18px;font-weight:700}.tn-stepper__step-header--error .tn-stepper__step-title{color:var(--tn-fg1, #000000)}.tn-stepper__step-header--active.tn-stepper__step-header--error .tn-stepper__step-title{color:var(--tn-fg2, #6c757d);font-weight:600}.tn-stepper__step-header--optional .tn-stepper__step-indicator{border:2px dashed var(--tn-lines, #e5e7eb);background:transparent}.tn-stepper--horizontal .tn-stepper__step-header--completed+.tn-stepper__connector{background:var(--tn-green, #28a745)}.tn-stepper--horizontal .tn-stepper__step-header--completed+.tn-stepper__connector:after{content:\"\";position:absolute;top:0;left:0;right:0;height:100%;background:var(--tn-green, #28a745);animation:progressFill .3s ease-in-out}.tn-stepper--vertical .tn-stepper__step-header--completed+.tn-stepper__connector{background:var(--tn-green, #28a745)}.tn-stepper__content{min-height:200px}.tn-stepper__step-content{padding:16px;background:var(--tn-bg1, #ffffff);border-radius:8px;border:1px solid var(--tn-lines, #e5e7eb)}@keyframes progressFill{0%{width:0}to{width:100%}}.tn-stepper__step-header:focus{outline:2px solid var(--tn-primary, #007bff);outline-offset:2px}.tn-stepper__step-header:focus:not(:focus-visible){outline:none}@media(max-width:780px){.tn-stepper--vertical .tn-stepper__header{width:180px;border-right:none;border-bottom:1px solid var(--tn-lines, #e5e7eb);padding:16px 0}.tn-stepper--vertical .tn-stepper__step-header{flex-direction:column;align-items:center;text-align:center;min-width:80px;padding:8px 4px}.tn-stepper--vertical .tn-stepper__step-header .tn-stepper__step-label{margin-left:0;margin-top:8px}.tn-stepper--vertical .tn-stepper__connector{display:none}}@media(max-width:780px){.tn-stepper .tn-stepper__step-label{display:none}.tn-stepper .tn-stepper__step-indicator{width:var(--step-diameter-sm);height:var(--step-diameter-sm);font-size:12px}.tn-stepper--horizontal .tn-stepper__header{padding:0 8px}.tn-stepper--horizontal .tn-stepper__connector{top:calc(var(--step-diameter-sm) / 2);margin:0 8px}.tn-stepper--vertical .tn-stepper__header{width:60px}.tn-stepper--vertical .tn-stepper__step-header{padding:4px;margin-bottom:4px}.tn-stepper--vertical .tn-stepper__connector{left:calc(var(--step-diameter-sm) / 2 + 4px);height:16px;margin-bottom:4px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TnTestIdDirective, selector: "[tnTestId]", inputs: ["tnTestId", "tnTestIdType"] }, { kind: "pipe", type: LabelMarkupPipe, name: "tnLabelMarkup" }], animations: [
|
|
15870
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnStepperComponent, isStandalone: true, selector: "tn-stepper", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, linear: { classPropertyName: "linear", publicName: "linear", isSignal: true, isRequired: false, transformFunction: null }, selectedIndex: { classPropertyName: "selectedIndex", publicName: "selectedIndex", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selectedIndex: "selectedIndexChange", selectionChange: "selectionChange", completed: "completed" }, host: { listeners: { "window:resize": "onWindowResize()" } }, queries: [{ propertyName: "steps", predicate: TnStepComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"tn-stepper\"\n tnTestIdType=\"stepper\"\n [class.tn-stepper--horizontal]=\"!isVertical()\"\n [class.tn-stepper--vertical]=\"isVertical()\"\n [tnTestId]=\"testId()\">\n\n <!-- Shared step header (indicator + label) -->\n <ng-template #stepHeader let-step=\"step\" let-i=\"i\">\n <div class=\"tn-stepper__step-header\"\n role=\"button\"\n [attr.tabindex]=\"stepGated()[i] ? -1 : 0\"\n [attr.aria-current]=\"selectedIndex() === i ? 'step' : null\"\n [attr.aria-disabled]=\"stepGated()[i] ? 'true' : null\"\n [class.tn-stepper__step-header--active]=\"selectedIndex() === i\"\n [class.tn-stepper__step-header--completed]=\"step.completed()\"\n [class.tn-stepper__step-header--error]=\"step.hasError()\"\n [class.tn-stepper__step-header--optional]=\"step.optional()\"\n (click)=\"selectStep(i)\"\n (keydown.enter)=\"selectStep(i)\"\n (keydown.space)=\"$event.preventDefault(); selectStep(i)\">\n\n <!-- Step Number/Icon -->\n <div class=\"tn-stepper__step-indicator\"\n [class.tn-stepper__step-indicator--glyph]=\"step.hasError()\">\n @if (step.hasError()) {\n <tn-icon class=\"tn-stepper__step-error\" name=\"alert\" library=\"mdi\" [attr.aria-hidden]=\"true\" />\n } @else if (stepEditable()[i]) {\n <tn-icon class=\"tn-stepper__step-edit\" name=\"pencil\" library=\"mdi\" [attr.aria-hidden]=\"true\" />\n } @else if (step.icon()) {\n <span class=\"tn-stepper__step-icon\">{{ step.icon() }}</span>\n } @else {\n <span class=\"tn-stepper__step-number\">{{ i + 1 }}</span>\n }\n </div>\n\n <!-- Step Label -->\n <div class=\"tn-stepper__step-label\">\n <div class=\"tn-stepper__step-title\" [innerHTML]=\"step.label() | tnLabelMarkup\"></div>\n @if (step.hasError() && step.errorMessage()) {\n <span class=\"tn-stepper__step-error-message\">{{ step.errorMessage() }}</span>\n } @else if (step.optional()) {\n <span class=\"tn-stepper__step-subtitle\">Optional</span>\n }\n </div>\n </div>\n </ng-template>\n\n @if (isVertical()) {\n <!-- Vertical: content renders inline beneath the active step's header -->\n <div class=\"tn-stepper__header\">\n @for (step of steps(); track $index; let i = $index) {\n <div class=\"tn-stepper__step\" [class.tn-stepper__step--last]=\"i === steps().length - 1\">\n <ng-container *ngTemplateOutlet=\"stepHeader; context: { step, i }\" />\n\n <div class=\"tn-stepper__step-body\">\n @if (selectedIndex() === i) {\n <div class=\"tn-stepper__step-content\" [@stepTransition]=\"selectedIndex()\">\n <ng-container *ngTemplateOutlet=\"step.content()\" />\n </div>\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <!-- Horizontal: headers in a row, active content below -->\n <div class=\"tn-stepper__header\">\n @for (step of steps(); track $index; let i = $index) {\n <ng-container *ngTemplateOutlet=\"stepHeader; context: { step, i }\" />\n\n @if (i < steps().length - 1) {\n <div class=\"tn-stepper__connector\"></div>\n }\n }\n </div>\n\n <div class=\"tn-stepper__content\">\n @for (step of steps(); track $index; let i = $index) {\n @if (selectedIndex() === i) {\n <div class=\"tn-stepper__step-content\"\n [@stepTransition]=\"selectedIndex()\">\n <ng-container *ngTemplateOutlet=\"step.content()\" />\n </div>\n }\n }\n </div>\n }\n</div>\n", styles: [".tn-stepper{display:flex;font-family:inherit;--step-diameter: 48px;--step-diameter-sm: 32px;--step-padding: 12px;--v-indicator: 32px;--v-gap: 12px}.tn-stepper--horizontal{flex-direction:column}.tn-stepper--horizontal .tn-stepper__header{display:flex;justify-content:center;margin-bottom:32px;padding:0 16px}.tn-stepper--horizontal .tn-stepper__step-header{display:flex;flex-direction:column;align-items:center;text-align:center;cursor:pointer;transition:all .2s ease-in-out}.tn-stepper--horizontal .tn-stepper__step-header:not(.tn-stepper__step-header--active):hover .tn-stepper__step-indicator{transform:scale(.95)}.tn-stepper--horizontal .tn-stepper__connector{flex:1;height:2px;background:var(--tn-lines, #e5e7eb);margin:0 16px;position:relative;top:calc(var(--step-diameter) / 2)}.tn-stepper--vertical{flex-direction:column}.tn-stepper--vertical .tn-stepper__header,.tn-stepper--vertical .tn-stepper__step{display:flex;flex-direction:column}.tn-stepper--vertical .tn-stepper__step-header{display:flex;flex-direction:row;align-items:center;gap:var(--v-gap);text-align:left;cursor:pointer;padding:8px 0}.tn-stepper--vertical .tn-stepper__step-header .tn-stepper__step-label{margin:0}.tn-stepper--vertical .tn-stepper__step-indicator{width:var(--v-indicator);height:var(--v-indicator);min-width:var(--v-indicator);font-size:13px;transform:none}.tn-stepper--vertical .tn-stepper__step-indicator--glyph tn-icon{--tn-icon-size: var(--v-indicator)}.tn-stepper--vertical .tn-stepper__step-header--active .tn-stepper__step-indicator{transform:none}.tn-stepper--vertical .tn-stepper__step-body{margin-left:calc(var(--v-indicator) / 2 - 1px);border-left:2px solid var(--tn-lines, #e5e7eb);padding-left:calc(var(--v-indicator) / 2 + var(--v-gap));padding-bottom:8px;min-height:12px}.tn-stepper--vertical .tn-stepper__step--last .tn-stepper__step-body{border-left-color:transparent;min-height:0}.tn-stepper--vertical .tn-stepper__step-content{padding:4px 0 8px;background:transparent;border:none;border-radius:0}.tn-stepper__step-indicator{display:flex;align-items:center;justify-content:center;width:var(--step-diameter);height:var(--step-diameter);border-radius:50%;background:var(--tn-alt-bg1, #f8f9fa);color:var(--tn-alt-fg1, #495057);font-weight:400;font-size:14px;transition:all .2s ease-in-out;position:relative;transform:scale(.65)}.tn-stepper__step-number{font-weight:400}.tn-stepper__step-edit{--tn-icon-size: 18px}.tn-stepper__step-label{margin-top:8px}.tn-stepper__step-title ::ng-deep code{font-family:var(--tn-font-family-monospace, monospace);font-size:.875em;background:var(--tn-bg2, #f5f5f5);border:1px solid var(--tn-lines, #ccc);border-radius:4px;padding:.125em .45em}.tn-stepper__step-title{display:block;font-weight:400;font-size:14px;color:var(--tn-fg1, #000000);line-height:1.2}.tn-stepper__step-subtitle{display:block;font-size:12px;color:var(--tn-fg2, #6c757d);margin-top:2px}.tn-stepper__step-error-message{display:block;font-size:12px;color:var(--tn-red, #dc3545);margin-top:2px}.tn-stepper__step-header--active .tn-stepper__step-indicator{background:var(--tn-primary, #007bff);color:var(--tn-primary-txt, #ffffff);transform:scale(1)}.tn-stepper__step-header--active .tn-stepper__step-title{color:var(--tn-fg2, #6c757d);font-weight:600}.tn-stepper__step-indicator.tn-stepper__step-indicator--glyph{background:transparent;transform:scale(1)}.tn-stepper__step-indicator.tn-stepper__step-indicator--glyph tn-icon{--tn-icon-size: var(--step-diameter);line-height:1}.tn-stepper__step-header--active .tn-stepper__step-indicator.tn-stepper__step-indicator--glyph{background:transparent}.tn-stepper__step-header--error .tn-stepper__step-error{--tn-icon-color: var(--tn-red, #dc3545)}.tn-stepper__step-header--error .tn-stepper__step-title{color:var(--tn-fg1, #000000)}.tn-stepper__step-header--active.tn-stepper__step-header--error .tn-stepper__step-title{color:var(--tn-fg2, #6c757d);font-weight:600}.tn-stepper__step-header--optional .tn-stepper__step-indicator{border:2px dashed var(--tn-lines, #e5e7eb);background:transparent}.tn-stepper__content{min-height:200px}.tn-stepper__step-content{padding:16px;background:var(--tn-bg1, #ffffff);border-radius:8px;border:1px solid var(--tn-lines, #e5e7eb)}.tn-stepper__step-header:focus{outline:2px solid var(--tn-primary, #007bff);outline-offset:2px}.tn-stepper__step-header:focus:not(:focus-visible){outline:none}.tn-stepper__step-header[aria-disabled=true]{cursor:not-allowed}@media(max-width:780px){.tn-stepper--horizontal .tn-stepper__step-label{display:none}.tn-stepper--horizontal .tn-stepper__step-indicator{width:var(--step-diameter-sm);height:var(--step-diameter-sm);font-size:12px}.tn-stepper--horizontal .tn-stepper__header{padding:0 8px}.tn-stepper--horizontal .tn-stepper__connector{top:calc(var(--step-diameter-sm) / 2);margin:0 8px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: TnTestIdDirective, selector: "[tnTestId]", inputs: ["tnTestId", "tnTestIdType"] }, { kind: "component", type: TnIconComponent, selector: "tn-icon", inputs: ["name", "size", "color", "tooltip", "ariaLabel", "library", "testId", "fullSize", "customSize"] }, { kind: "pipe", type: LabelMarkupPipe, name: "tnLabelMarkup" }], animations: [
|
|
15839
15871
|
trigger('stepTransition', [
|
|
15840
15872
|
transition(':enter', [
|
|
15841
15873
|
style({ opacity: 0, transform: 'translateX(50px)' }),
|
|
@@ -15846,7 +15878,7 @@ class TnStepperComponent {
|
|
|
15846
15878
|
}
|
|
15847
15879
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnStepperComponent, decorators: [{
|
|
15848
15880
|
type: Component,
|
|
15849
|
-
args: [{ selector: 'tn-stepper', standalone: true, imports: [CommonModule, TnTestIdDirective, LabelMarkupPipe], animations: [
|
|
15881
|
+
args: [{ selector: 'tn-stepper', standalone: true, imports: [CommonModule, TnTestIdDirective, LabelMarkupPipe, TnIconComponent], animations: [
|
|
15850
15882
|
trigger('stepTransition', [
|
|
15851
15883
|
transition(':enter', [
|
|
15852
15884
|
style({ opacity: 0, transform: 'translateX(50px)' }),
|
|
@@ -15854,10 +15886,139 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
15854
15886
|
])
|
|
15855
15887
|
])
|
|
15856
15888
|
], host: {
|
|
15857
|
-
'(window:resize)': 'onWindowResize(
|
|
15858
|
-
}, template: "<div class=\"tn-stepper\"\n tnTestIdType=\"stepper\"\n [class.tn-stepper--horizontal]=\"
|
|
15889
|
+
'(window:resize)': 'onWindowResize()'
|
|
15890
|
+
}, template: "<div class=\"tn-stepper\"\n tnTestIdType=\"stepper\"\n [class.tn-stepper--horizontal]=\"!isVertical()\"\n [class.tn-stepper--vertical]=\"isVertical()\"\n [tnTestId]=\"testId()\">\n\n <!-- Shared step header (indicator + label) -->\n <ng-template #stepHeader let-step=\"step\" let-i=\"i\">\n <div class=\"tn-stepper__step-header\"\n role=\"button\"\n [attr.tabindex]=\"stepGated()[i] ? -1 : 0\"\n [attr.aria-current]=\"selectedIndex() === i ? 'step' : null\"\n [attr.aria-disabled]=\"stepGated()[i] ? 'true' : null\"\n [class.tn-stepper__step-header--active]=\"selectedIndex() === i\"\n [class.tn-stepper__step-header--completed]=\"step.completed()\"\n [class.tn-stepper__step-header--error]=\"step.hasError()\"\n [class.tn-stepper__step-header--optional]=\"step.optional()\"\n (click)=\"selectStep(i)\"\n (keydown.enter)=\"selectStep(i)\"\n (keydown.space)=\"$event.preventDefault(); selectStep(i)\">\n\n <!-- Step Number/Icon -->\n <div class=\"tn-stepper__step-indicator\"\n [class.tn-stepper__step-indicator--glyph]=\"step.hasError()\">\n @if (step.hasError()) {\n <tn-icon class=\"tn-stepper__step-error\" name=\"alert\" library=\"mdi\" [attr.aria-hidden]=\"true\" />\n } @else if (stepEditable()[i]) {\n <tn-icon class=\"tn-stepper__step-edit\" name=\"pencil\" library=\"mdi\" [attr.aria-hidden]=\"true\" />\n } @else if (step.icon()) {\n <span class=\"tn-stepper__step-icon\">{{ step.icon() }}</span>\n } @else {\n <span class=\"tn-stepper__step-number\">{{ i + 1 }}</span>\n }\n </div>\n\n <!-- Step Label -->\n <div class=\"tn-stepper__step-label\">\n <div class=\"tn-stepper__step-title\" [innerHTML]=\"step.label() | tnLabelMarkup\"></div>\n @if (step.hasError() && step.errorMessage()) {\n <span class=\"tn-stepper__step-error-message\">{{ step.errorMessage() }}</span>\n } @else if (step.optional()) {\n <span class=\"tn-stepper__step-subtitle\">Optional</span>\n }\n </div>\n </div>\n </ng-template>\n\n @if (isVertical()) {\n <!-- Vertical: content renders inline beneath the active step's header -->\n <div class=\"tn-stepper__header\">\n @for (step of steps(); track $index; let i = $index) {\n <div class=\"tn-stepper__step\" [class.tn-stepper__step--last]=\"i === steps().length - 1\">\n <ng-container *ngTemplateOutlet=\"stepHeader; context: { step, i }\" />\n\n <div class=\"tn-stepper__step-body\">\n @if (selectedIndex() === i) {\n <div class=\"tn-stepper__step-content\" [@stepTransition]=\"selectedIndex()\">\n <ng-container *ngTemplateOutlet=\"step.content()\" />\n </div>\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <!-- Horizontal: headers in a row, active content below -->\n <div class=\"tn-stepper__header\">\n @for (step of steps(); track $index; let i = $index) {\n <ng-container *ngTemplateOutlet=\"stepHeader; context: { step, i }\" />\n\n @if (i < steps().length - 1) {\n <div class=\"tn-stepper__connector\"></div>\n }\n }\n </div>\n\n <div class=\"tn-stepper__content\">\n @for (step of steps(); track $index; let i = $index) {\n @if (selectedIndex() === i) {\n <div class=\"tn-stepper__step-content\"\n [@stepTransition]=\"selectedIndex()\">\n <ng-container *ngTemplateOutlet=\"step.content()\" />\n </div>\n }\n }\n </div>\n }\n</div>\n", styles: [".tn-stepper{display:flex;font-family:inherit;--step-diameter: 48px;--step-diameter-sm: 32px;--step-padding: 12px;--v-indicator: 32px;--v-gap: 12px}.tn-stepper--horizontal{flex-direction:column}.tn-stepper--horizontal .tn-stepper__header{display:flex;justify-content:center;margin-bottom:32px;padding:0 16px}.tn-stepper--horizontal .tn-stepper__step-header{display:flex;flex-direction:column;align-items:center;text-align:center;cursor:pointer;transition:all .2s ease-in-out}.tn-stepper--horizontal .tn-stepper__step-header:not(.tn-stepper__step-header--active):hover .tn-stepper__step-indicator{transform:scale(.95)}.tn-stepper--horizontal .tn-stepper__connector{flex:1;height:2px;background:var(--tn-lines, #e5e7eb);margin:0 16px;position:relative;top:calc(var(--step-diameter) / 2)}.tn-stepper--vertical{flex-direction:column}.tn-stepper--vertical .tn-stepper__header,.tn-stepper--vertical .tn-stepper__step{display:flex;flex-direction:column}.tn-stepper--vertical .tn-stepper__step-header{display:flex;flex-direction:row;align-items:center;gap:var(--v-gap);text-align:left;cursor:pointer;padding:8px 0}.tn-stepper--vertical .tn-stepper__step-header .tn-stepper__step-label{margin:0}.tn-stepper--vertical .tn-stepper__step-indicator{width:var(--v-indicator);height:var(--v-indicator);min-width:var(--v-indicator);font-size:13px;transform:none}.tn-stepper--vertical .tn-stepper__step-indicator--glyph tn-icon{--tn-icon-size: var(--v-indicator)}.tn-stepper--vertical .tn-stepper__step-header--active .tn-stepper__step-indicator{transform:none}.tn-stepper--vertical .tn-stepper__step-body{margin-left:calc(var(--v-indicator) / 2 - 1px);border-left:2px solid var(--tn-lines, #e5e7eb);padding-left:calc(var(--v-indicator) / 2 + var(--v-gap));padding-bottom:8px;min-height:12px}.tn-stepper--vertical .tn-stepper__step--last .tn-stepper__step-body{border-left-color:transparent;min-height:0}.tn-stepper--vertical .tn-stepper__step-content{padding:4px 0 8px;background:transparent;border:none;border-radius:0}.tn-stepper__step-indicator{display:flex;align-items:center;justify-content:center;width:var(--step-diameter);height:var(--step-diameter);border-radius:50%;background:var(--tn-alt-bg1, #f8f9fa);color:var(--tn-alt-fg1, #495057);font-weight:400;font-size:14px;transition:all .2s ease-in-out;position:relative;transform:scale(.65)}.tn-stepper__step-number{font-weight:400}.tn-stepper__step-edit{--tn-icon-size: 18px}.tn-stepper__step-label{margin-top:8px}.tn-stepper__step-title ::ng-deep code{font-family:var(--tn-font-family-monospace, monospace);font-size:.875em;background:var(--tn-bg2, #f5f5f5);border:1px solid var(--tn-lines, #ccc);border-radius:4px;padding:.125em .45em}.tn-stepper__step-title{display:block;font-weight:400;font-size:14px;color:var(--tn-fg1, #000000);line-height:1.2}.tn-stepper__step-subtitle{display:block;font-size:12px;color:var(--tn-fg2, #6c757d);margin-top:2px}.tn-stepper__step-error-message{display:block;font-size:12px;color:var(--tn-red, #dc3545);margin-top:2px}.tn-stepper__step-header--active .tn-stepper__step-indicator{background:var(--tn-primary, #007bff);color:var(--tn-primary-txt, #ffffff);transform:scale(1)}.tn-stepper__step-header--active .tn-stepper__step-title{color:var(--tn-fg2, #6c757d);font-weight:600}.tn-stepper__step-indicator.tn-stepper__step-indicator--glyph{background:transparent;transform:scale(1)}.tn-stepper__step-indicator.tn-stepper__step-indicator--glyph tn-icon{--tn-icon-size: var(--step-diameter);line-height:1}.tn-stepper__step-header--active .tn-stepper__step-indicator.tn-stepper__step-indicator--glyph{background:transparent}.tn-stepper__step-header--error .tn-stepper__step-error{--tn-icon-color: var(--tn-red, #dc3545)}.tn-stepper__step-header--error .tn-stepper__step-title{color:var(--tn-fg1, #000000)}.tn-stepper__step-header--active.tn-stepper__step-header--error .tn-stepper__step-title{color:var(--tn-fg2, #6c757d);font-weight:600}.tn-stepper__step-header--optional .tn-stepper__step-indicator{border:2px dashed var(--tn-lines, #e5e7eb);background:transparent}.tn-stepper__content{min-height:200px}.tn-stepper__step-content{padding:16px;background:var(--tn-bg1, #ffffff);border-radius:8px;border:1px solid var(--tn-lines, #e5e7eb)}.tn-stepper__step-header:focus{outline:2px solid var(--tn-primary, #007bff);outline-offset:2px}.tn-stepper__step-header:focus:not(:focus-visible){outline:none}.tn-stepper__step-header[aria-disabled=true]{cursor:not-allowed}@media(max-width:780px){.tn-stepper--horizontal .tn-stepper__step-label{display:none}.tn-stepper--horizontal .tn-stepper__step-indicator{width:var(--step-diameter-sm);height:var(--step-diameter-sm);font-size:12px}.tn-stepper--horizontal .tn-stepper__header{padding:0 8px}.tn-stepper--horizontal .tn-stepper__connector{top:calc(var(--step-diameter-sm) / 2);margin:0 8px}}\n"] }]
|
|
15859
15891
|
}], ctorParameters: () => [], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], linear: [{ type: i0.Input, args: [{ isSignal: true, alias: "linear", required: false }] }], selectedIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIndex", required: false }] }, { type: i0.Output, args: ["selectedIndexChange"] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], completed: [{ type: i0.Output, args: ["completed"] }], steps: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TnStepComponent), { ...{ descendants: true }, isSignal: true }] }] } });
|
|
15860
15892
|
|
|
15893
|
+
/**
|
|
15894
|
+
* Advances the ancestor `<tn-stepper>` to the next step when the host is clicked.
|
|
15895
|
+
*
|
|
15896
|
+
* Mirrors Angular Material's `matStepperNext`. Place it on a button (native
|
|
15897
|
+
* `<button>` or `<tn-button>`) rendered inside a `<tn-step>` — including step
|
|
15898
|
+
* content that lives in a projected child component. The directive resolves the
|
|
15899
|
+
* stepper through the element injector, so a disabled host simply emits no click
|
|
15900
|
+
* and navigation is naturally gated.
|
|
15901
|
+
*
|
|
15902
|
+
* @example
|
|
15903
|
+
* ```html
|
|
15904
|
+
* <tn-button [tnStepperNext] [disabled]="form.invalid" [label]="'Next' | translate" />
|
|
15905
|
+
* ```
|
|
15906
|
+
*/
|
|
15907
|
+
class TnStepperNextDirective {
|
|
15908
|
+
stepper = inject(TnStepperComponent);
|
|
15909
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnStepperNextDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
15910
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: TnStepperNextDirective, isStandalone: true, selector: "[tnStepperNext]", host: { listeners: { "click": "stepper.next()" } }, ngImport: i0 });
|
|
15911
|
+
}
|
|
15912
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnStepperNextDirective, decorators: [{
|
|
15913
|
+
type: Directive,
|
|
15914
|
+
args: [{
|
|
15915
|
+
selector: '[tnStepperNext]',
|
|
15916
|
+
standalone: true,
|
|
15917
|
+
host: {
|
|
15918
|
+
'(click)': 'stepper.next()',
|
|
15919
|
+
},
|
|
15920
|
+
}]
|
|
15921
|
+
}] });
|
|
15922
|
+
|
|
15923
|
+
/**
|
|
15924
|
+
* Moves the ancestor `<tn-stepper>` to the previous step when the host is clicked.
|
|
15925
|
+
*
|
|
15926
|
+
* Mirrors Angular Material's `matStepperPrevious`. Place it on a button (native
|
|
15927
|
+
* `<button>` or `<tn-button>`) rendered inside a `<tn-step>` — including step
|
|
15928
|
+
* content that lives in a projected child component. The directive resolves the
|
|
15929
|
+
* stepper through the element injector.
|
|
15930
|
+
*
|
|
15931
|
+
* @example
|
|
15932
|
+
* ```html
|
|
15933
|
+
* <tn-button [tnStepperPrevious] [label]="'Back' | translate" />
|
|
15934
|
+
* ```
|
|
15935
|
+
*/
|
|
15936
|
+
class TnStepperPreviousDirective {
|
|
15937
|
+
stepper = inject(TnStepperComponent);
|
|
15938
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnStepperPreviousDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
15939
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: TnStepperPreviousDirective, isStandalone: true, selector: "[tnStepperPrevious]", host: { listeners: { "click": "stepper.previous()" } }, ngImport: i0 });
|
|
15940
|
+
}
|
|
15941
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnStepperPreviousDirective, decorators: [{
|
|
15942
|
+
type: Directive,
|
|
15943
|
+
args: [{
|
|
15944
|
+
selector: '[tnStepperPrevious]',
|
|
15945
|
+
standalone: true,
|
|
15946
|
+
host: {
|
|
15947
|
+
'(click)': 'stepper.previous()',
|
|
15948
|
+
},
|
|
15949
|
+
}]
|
|
15950
|
+
}] });
|
|
15951
|
+
|
|
15952
|
+
/**
|
|
15953
|
+
* Harness for interacting with `tn-stepper` in tests.
|
|
15954
|
+
*
|
|
15955
|
+
* @example
|
|
15956
|
+
* ```typescript
|
|
15957
|
+
* const stepper = await loader.getHarness(TnStepperHarness);
|
|
15958
|
+
* expect(await stepper.getStepLabels()).toEqual(['Provider', 'What and When']);
|
|
15959
|
+
* expect(await stepper.getSelectedIndex()).toBe(0);
|
|
15960
|
+
* await stepper.selectStep(1);
|
|
15961
|
+
* ```
|
|
15962
|
+
*/
|
|
15963
|
+
class TnStepperHarness extends ComponentHarness {
|
|
15964
|
+
/** The selector for the host element of a `TnStepperComponent` instance. */
|
|
15965
|
+
static hostSelector = 'tn-stepper';
|
|
15966
|
+
/**
|
|
15967
|
+
* Gets a `HarnessPredicate` used to search for a stepper with specific attributes.
|
|
15968
|
+
*
|
|
15969
|
+
* @param options Options for filtering which stepper instances are considered a match.
|
|
15970
|
+
*/
|
|
15971
|
+
static with(options = {}) {
|
|
15972
|
+
return new HarnessPredicate(TnStepperHarness, options)
|
|
15973
|
+
.addOption('orientation', options.orientation, async (harness, orientation) => {
|
|
15974
|
+
return (await harness.getOrientation()) === orientation;
|
|
15975
|
+
});
|
|
15976
|
+
}
|
|
15977
|
+
headers = this.locatorForAll('.tn-stepper__step-header');
|
|
15978
|
+
/** Gets the number of steps. */
|
|
15979
|
+
async getStepCount() {
|
|
15980
|
+
return (await this.headers()).length;
|
|
15981
|
+
}
|
|
15982
|
+
/** Gets all step labels as strings, in order. */
|
|
15983
|
+
async getStepLabels() {
|
|
15984
|
+
const titles = await this.locatorForAll('.tn-stepper__step-title')();
|
|
15985
|
+
return Promise.all(titles.map(title => title.text()));
|
|
15986
|
+
}
|
|
15987
|
+
/** Gets the zero-based index of the currently selected step, or -1 if none. */
|
|
15988
|
+
async getSelectedIndex() {
|
|
15989
|
+
const headers = await this.headers();
|
|
15990
|
+
for (let i = 0; i < headers.length; i++) {
|
|
15991
|
+
if (await headers[i].hasClass('tn-stepper__step-header--active')) {
|
|
15992
|
+
return i;
|
|
15993
|
+
}
|
|
15994
|
+
}
|
|
15995
|
+
return -1;
|
|
15996
|
+
}
|
|
15997
|
+
/** Whether the step at `index` is marked completed. */
|
|
15998
|
+
async isStepCompleted(index) {
|
|
15999
|
+
const header = (await this.headers())[index];
|
|
16000
|
+
return header ? header.hasClass('tn-stepper__step-header--completed') : false;
|
|
16001
|
+
}
|
|
16002
|
+
/** Whether the step at `index` is marked as having an error. */
|
|
16003
|
+
async isStepError(index) {
|
|
16004
|
+
const header = (await this.headers())[index];
|
|
16005
|
+
return header ? header.hasClass('tn-stepper__step-header--error') : false;
|
|
16006
|
+
}
|
|
16007
|
+
/** Selects the step at `index` by clicking its header. Respects linear gating. */
|
|
16008
|
+
async selectStep(index) {
|
|
16009
|
+
const header = (await this.headers())[index];
|
|
16010
|
+
if (!header) {
|
|
16011
|
+
throw new Error(`No step at index ${index}`);
|
|
16012
|
+
}
|
|
16013
|
+
await header.click();
|
|
16014
|
+
}
|
|
16015
|
+
/** Gets the orientation of the stepper. */
|
|
16016
|
+
async getOrientation() {
|
|
16017
|
+
const root = await this.locatorFor('.tn-stepper')();
|
|
16018
|
+
return (await root.hasClass('tn-stepper--vertical')) ? 'vertical' : 'horizontal';
|
|
16019
|
+
}
|
|
16020
|
+
}
|
|
16021
|
+
|
|
15861
16022
|
/**
|
|
15862
16023
|
* Auto-generated from SVG files - DO NOT EDIT MANUALLY
|
|
15863
16024
|
*
|
|
@@ -17674,5 +17835,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
17674
17835
|
* Generated bundle index. Do not edit.
|
|
17675
17836
|
*/
|
|
17676
17837
|
|
|
17677
|
-
export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LIGHT_THEME, LabelMarkupPipe, LabelTextPipe, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, StripMntPrefixPipe, THEME_MAP, THEME_STORAGE_KEY, TN_FORM_FIELD_ERRORS, TN_TABLE_PAGER_DEFAULT_LABELS, TN_TABLE_PAGER_LABELS, TN_TEST_ATTR, TN_THEME_DEFINITIONS, TnAutocompleteComponent, TnAutocompleteHarness, TnBannerActionDirective, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnButtonToggleGroupHarness, TnButtonToggleHarness, TnCalendarComponent, TnCalendarHeaderComponent, TnCardComponent, TnCardFooterActionsDirective, TnCardHeaderActionsDirective, TnCardHeaderDirective, TnCellDefDirective, TnCheckboxComponent, TnCheckboxHarness, TnCheckboxLabelDirective, TnChipComponent, TnChipHarness, TnChipInputComponent, TnChipInputHarness, TnConfirmDialogComponent, TnDateInputComponent, TnDateInputHarness, TnDateRangeInputComponent, TnDateRangeInputHarness, TnDetailRowDefDirective, TnDialog, TnDialogHarness, TnDialogShellComponent, TnDialogTesting, TnDividerComponent, TnDividerDirective, TnDrawerComponent, TnDrawerContainerComponent, TnDrawerContainerHarness, TnDrawerContentComponent, TnDrawerHarness, TnEmptyComponent, TnEmptyHarness, TnExpansionPanelComponent, TnExpansionPanelHarness, TnFileInputComponent, TnFileInputHarness, TnFilePickerComponent, TnFilePickerPopupComponent, TnFormFieldComponent, TnFormFieldHarness, TnFormSectionComponent, TnFormSectionHarness, TnHeaderCellDefDirective, TnIconButtonComponent, TnIconButtonHarness, TnIconComponent, TnIconHarness, TnIconRegistryService, TnIconTesting, TnInputComponent, TnInputDirective, TnInputHarness, TnKeyboardShortcutComponent, TnKeyboardShortcutService, TnListAvatarDirective, TnListComponent, TnListIconDirective, TnListItemComponent, TnListItemLineDirective, TnListItemPrimaryDirective, TnListItemSecondaryDirective, TnListItemTitleDirective, TnListItemTrailingDirective, TnListOptionComponent, TnListSubheaderComponent, TnMenuActivateHoverDirective, TnMenuComponent, TnMenuHarness, TnMenuItemComponent, TnMenuTesting, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnRadioHarness, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSidePanelActionDirective, TnSidePanelComponent, TnSidePanelHarness, TnSidePanelHeaderActionDirective, TnSlideToggleComponent, TnSlideToggleHarness, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnTabComponent, TnTabHarness, TnTabPanelComponent, TnTabPanelHarness, TnTableColumnDirective, TnTableComponent, TnTableHarness, TnTablePagerComponent, TnTablePagerHarness, TnTabsComponent, TnTabsHarness, TnTestIdDirective, TnTheme, TnThemeService, TnTimeInputComponent, TnToastComponent, TnToastMock, TnToastPosition, TnToastRef, TnToastService, TnToastTesting, TnToastType, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeNodeComponent, TnTreeNodeOutletDirective, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, composeTestId, controlTestId, createLucideLibrary, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, formatSize, kebabTestSegment, labelMarkupToHtml, labelMarkupToText, libIconMarker, parseLabelMarkup, parseSize, registerLucideIcons, scopeTestId, setupLucideIntegration, tnIconMarker, writeTestId };
|
|
17838
|
+
export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LIGHT_THEME, LabelMarkupPipe, LabelTextPipe, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, StripMntPrefixPipe, THEME_MAP, THEME_STORAGE_KEY, TN_FORM_FIELD_ERRORS, TN_TABLE_PAGER_DEFAULT_LABELS, TN_TABLE_PAGER_LABELS, TN_TEST_ATTR, TN_THEME_DEFINITIONS, TnAutocompleteComponent, TnAutocompleteHarness, TnBannerActionDirective, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnButtonToggleGroupHarness, TnButtonToggleHarness, TnCalendarComponent, TnCalendarHeaderComponent, TnCardComponent, TnCardFooterActionsDirective, TnCardHeaderActionsDirective, TnCardHeaderDirective, TnCellDefDirective, TnCheckboxComponent, TnCheckboxHarness, TnCheckboxLabelDirective, TnChipComponent, TnChipHarness, TnChipInputComponent, TnChipInputHarness, TnConfirmDialogComponent, TnDateInputComponent, TnDateInputHarness, TnDateRangeInputComponent, TnDateRangeInputHarness, TnDetailRowDefDirective, TnDialog, TnDialogHarness, TnDialogShellComponent, TnDialogTesting, TnDividerComponent, TnDividerDirective, TnDrawerComponent, TnDrawerContainerComponent, TnDrawerContainerHarness, TnDrawerContentComponent, TnDrawerHarness, TnEmptyComponent, TnEmptyHarness, TnExpansionPanelComponent, TnExpansionPanelHarness, TnFileInputComponent, TnFileInputHarness, TnFilePickerComponent, TnFilePickerPopupComponent, TnFormFieldComponent, TnFormFieldHarness, TnFormSectionComponent, TnFormSectionHarness, TnHeaderCellDefDirective, TnIconButtonComponent, TnIconButtonHarness, TnIconComponent, TnIconHarness, TnIconRegistryService, TnIconTesting, TnInputComponent, TnInputDirective, TnInputHarness, TnKeyboardShortcutComponent, TnKeyboardShortcutService, TnListAvatarDirective, TnListComponent, TnListIconDirective, TnListItemComponent, TnListItemLineDirective, TnListItemPrimaryDirective, TnListItemSecondaryDirective, TnListItemTitleDirective, TnListItemTrailingDirective, TnListOptionComponent, TnListSubheaderComponent, TnMenuActivateHoverDirective, TnMenuComponent, TnMenuHarness, TnMenuItemComponent, TnMenuTesting, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnRadioHarness, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSidePanelActionDirective, TnSidePanelComponent, TnSidePanelHarness, TnSidePanelHeaderActionDirective, TnSlideToggleComponent, TnSlideToggleHarness, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnStepperHarness, TnStepperNextDirective, TnStepperPreviousDirective, TnTabComponent, TnTabHarness, TnTabPanelComponent, TnTabPanelHarness, TnTableColumnDirective, TnTableComponent, TnTableHarness, TnTablePagerComponent, TnTablePagerHarness, TnTabsComponent, TnTabsHarness, TnTestIdDirective, TnTheme, TnThemeService, TnTimeInputComponent, TnToastComponent, TnToastMock, TnToastPosition, TnToastRef, TnToastService, TnToastTesting, TnToastType, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeNodeComponent, TnTreeNodeOutletDirective, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, composeTestId, controlTestId, createLucideLibrary, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, formatSize, kebabTestSegment, labelMarkupToHtml, labelMarkupToText, libIconMarker, parseLabelMarkup, parseSize, registerLucideIcons, scopeTestId, setupLucideIntegration, tnIconMarker, writeTestId };
|
|
17678
17839
|
//# sourceMappingURL=truenas-ui-components.mjs.map
|