@truenas/ui-components 0.1.15 → 0.1.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.
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, ChangeDetectionStrategy, Component, inject, Injectable, viewChild, signal, effect, computed, ViewEncapsulation, Directive, contentChildren, output, forwardRef, ElementRef, ViewContainerRef, contentChild, ChangeDetectorRef, HostListener, TemplateRef, IterableDiffers, Pipe, model, PLATFORM_ID } from '@angular/core';
|
|
2
|
+
import { input, ChangeDetectionStrategy, Component, inject, Injectable, viewChild, signal, effect, computed, ViewEncapsulation, Directive, contentChildren, output, forwardRef, ElementRef, ViewContainerRef, contentChild, ChangeDetectorRef, HostListener, TemplateRef, IterableDiffers, Pipe, model, afterNextRender, PLATFORM_ID } from '@angular/core';
|
|
3
3
|
import * as i1$1 from '@angular/common';
|
|
4
4
|
import { CommonModule, DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
5
|
-
import { mdiCheckCircle, mdiAlertCircle, mdiAlert, mdiInformation, mdiDotsVertical, mdiFolderOpen, mdiLock, mdiLoading, mdiFolderPlus, mdiFolderNetwork, mdiHarddisk, mdiDatabase, mdiFile, mdiFolder } from '@mdi/js';
|
|
5
|
+
import { mdiCheckCircle, mdiAlertCircle, mdiAlert, mdiInformation, mdiDotsVertical, mdiClose, mdiFolderOpen, mdiLock, mdiLoading, mdiFolderPlus, mdiFolderNetwork, mdiHarddisk, mdiDatabase, mdiFile, mdiFolder } from '@mdi/js';
|
|
6
6
|
import * as i1 from '@angular/platform-browser';
|
|
7
7
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
8
8
|
import { HttpClient } from '@angular/common/http';
|
|
9
9
|
import { firstValueFrom, BehaviorSubject, merge, Subject } from 'rxjs';
|
|
10
10
|
import { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
|
|
11
|
+
import * as i1$4 from '@angular/cdk/a11y';
|
|
11
12
|
import { FocusMonitor, A11yModule } from '@angular/cdk/a11y';
|
|
12
13
|
import * as i1$3 from '@angular/forms';
|
|
13
14
|
import { FormsModule, NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
|
|
@@ -7712,6 +7713,7 @@ class TnDialog {
|
|
|
7712
7713
|
return Promise.resolve().then(function () { return confirmDialog_component; }).then(m => {
|
|
7713
7714
|
const dialogRef = this.open(m.TnConfirmDialogComponent, {
|
|
7714
7715
|
data: opts,
|
|
7716
|
+
width: '488px',
|
|
7715
7717
|
role: 'alertdialog',
|
|
7716
7718
|
disableClose: true,
|
|
7717
7719
|
panelClass: [opts.destructive ? 'tn-dialog--destructive' : ''].filter(Boolean),
|
|
@@ -7805,14 +7807,14 @@ class TnConfirmDialogComponent {
|
|
|
7805
7807
|
ref = inject((DialogRef));
|
|
7806
7808
|
data = inject(DIALOG_DATA);
|
|
7807
7809
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnConfirmDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7808
|
-
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=\"
|
|
7810
|
+
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 (click)=\"ref.close(false)\" />\n <tn-button\n type=\"button\"\n [color]=\"data.destructive ? 'warn' : 'primary'\"\n [label]=\"data.confirmText || 'OK'\"\n (click)=\"ref.close(true)\" />\n </div>\n</tn-dialog-shell>\n", dependencies: [{ kind: "component", type: TnDialogShellComponent, selector: "tn-dialog-shell", inputs: ["title", "showFullscreenButton"] }, { kind: "component", type: TnButtonComponent, selector: "tn-button", inputs: ["primary", "color", "variant", "backgroundColor", "label", "disabled"], outputs: ["onClick"] }] });
|
|
7809
7811
|
}
|
|
7810
7812
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnConfirmDialogComponent, decorators: [{
|
|
7811
7813
|
type: Component,
|
|
7812
7814
|
args: [{ selector: 'tn-confirm-dialog', standalone: true, imports: [TnDialogShellComponent, TnButtonComponent], host: {
|
|
7813
7815
|
'class': 'tn-dialog-shell',
|
|
7814
7816
|
'[class.tn-dialog--destructive]': 'data.destructive'
|
|
7815
|
-
}, template: "<tn-dialog-shell [title]=\"data.title\">\n <p style=\"
|
|
7817
|
+
}, 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 (click)=\"ref.close(false)\" />\n <tn-button\n type=\"button\"\n [color]=\"data.destructive ? 'warn' : 'primary'\"\n [label]=\"data.confirmText || 'OK'\"\n (click)=\"ref.close(true)\" />\n </div>\n</tn-dialog-shell>\n" }]
|
|
7816
7818
|
}] });
|
|
7817
7819
|
|
|
7818
7820
|
var confirmDialog_component = /*#__PURE__*/Object.freeze({
|
|
@@ -7820,6 +7822,200 @@ var confirmDialog_component = /*#__PURE__*/Object.freeze({
|
|
|
7820
7822
|
TnConfirmDialogComponent: TnConfirmDialogComponent
|
|
7821
7823
|
});
|
|
7822
7824
|
|
|
7825
|
+
/**
|
|
7826
|
+
* Directive to mark an element as a side-panel footer action.
|
|
7827
|
+
*
|
|
7828
|
+
* @example
|
|
7829
|
+
* ```html
|
|
7830
|
+
* <tn-side-panel [(open)]="isOpen" title="Edit">
|
|
7831
|
+
* <tn-button tnSidePanelAction label="Save" />
|
|
7832
|
+
* </tn-side-panel>
|
|
7833
|
+
* ```
|
|
7834
|
+
*/
|
|
7835
|
+
class TnSidePanelActionDirective {
|
|
7836
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnSidePanelActionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
7837
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: TnSidePanelActionDirective, isStandalone: true, selector: "[tnSidePanelAction]", ngImport: i0 });
|
|
7838
|
+
}
|
|
7839
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnSidePanelActionDirective, decorators: [{
|
|
7840
|
+
type: Directive,
|
|
7841
|
+
args: [{
|
|
7842
|
+
selector: '[tnSidePanelAction]',
|
|
7843
|
+
standalone: true,
|
|
7844
|
+
}]
|
|
7845
|
+
}] });
|
|
7846
|
+
/**
|
|
7847
|
+
* Directive to mark an element as a side-panel header action.
|
|
7848
|
+
*
|
|
7849
|
+
* @example
|
|
7850
|
+
* ```html
|
|
7851
|
+
* <tn-side-panel [(open)]="isOpen" title="Edit">
|
|
7852
|
+
* <tn-icon-button tnSidePanelHeaderAction name="fullscreen" />
|
|
7853
|
+
* Content here
|
|
7854
|
+
* </tn-side-panel>
|
|
7855
|
+
* ```
|
|
7856
|
+
*/
|
|
7857
|
+
class TnSidePanelHeaderActionDirective {
|
|
7858
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnSidePanelHeaderActionDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
7859
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: TnSidePanelHeaderActionDirective, isStandalone: true, selector: "[tnSidePanelHeaderAction]", ngImport: i0 });
|
|
7860
|
+
}
|
|
7861
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnSidePanelHeaderActionDirective, decorators: [{
|
|
7862
|
+
type: Directive,
|
|
7863
|
+
args: [{
|
|
7864
|
+
selector: '[tnSidePanelHeaderAction]',
|
|
7865
|
+
standalone: true,
|
|
7866
|
+
}]
|
|
7867
|
+
}] });
|
|
7868
|
+
class TnSidePanelComponent {
|
|
7869
|
+
iconRegistry = inject(TnIconRegistryService);
|
|
7870
|
+
document = inject(DOCUMENT);
|
|
7871
|
+
overlayRef = viewChild.required('overlay');
|
|
7872
|
+
initialized = signal(false, ...(ngDevMode ? [{ debugName: "initialized" }] : []));
|
|
7873
|
+
// Two-way bindable via [(open)]
|
|
7874
|
+
open = model(false, ...(ngDevMode ? [{ debugName: "open" }] : []));
|
|
7875
|
+
// Inputs
|
|
7876
|
+
title = input('', ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
7877
|
+
width = input('480px', ...(ngDevMode ? [{ debugName: "width" }] : []));
|
|
7878
|
+
hasBackdrop = input(true, ...(ngDevMode ? [{ debugName: "hasBackdrop" }] : []));
|
|
7879
|
+
closeOnBackdropClick = input(true, ...(ngDevMode ? [{ debugName: "closeOnBackdropClick" }] : []));
|
|
7880
|
+
closeOnEscape = input(true, ...(ngDevMode ? [{ debugName: "closeOnEscape" }] : []));
|
|
7881
|
+
// Outputs
|
|
7882
|
+
opened = output();
|
|
7883
|
+
closed = output();
|
|
7884
|
+
// Content projection queries
|
|
7885
|
+
actionContent = contentChildren(TnSidePanelActionDirective, ...(ngDevMode ? [{ debugName: "actionContent" }] : []));
|
|
7886
|
+
hasActions = computed(() => this.actionContent().length > 0, ...(ngDevMode ? [{ debugName: "hasActions" }] : []));
|
|
7887
|
+
// Unique IDs for aria-labelledby and portal correlation
|
|
7888
|
+
panelId = `tn-side-panel-${Math.random().toString(36).substring(2, 9)}`;
|
|
7889
|
+
titleId = `${this.panelId}-title`;
|
|
7890
|
+
// Focus restoration
|
|
7891
|
+
previouslyFocusedElement = null;
|
|
7892
|
+
constructor() {
|
|
7893
|
+
this.registerMdiIcons();
|
|
7894
|
+
effect(() => {
|
|
7895
|
+
if (this.open()) {
|
|
7896
|
+
this.previouslyFocusedElement = this.document.activeElement;
|
|
7897
|
+
}
|
|
7898
|
+
});
|
|
7899
|
+
afterNextRender(() => {
|
|
7900
|
+
this.document.body.appendChild(this.overlayRef().nativeElement);
|
|
7901
|
+
this.initialized.set(true);
|
|
7902
|
+
});
|
|
7903
|
+
}
|
|
7904
|
+
ngOnDestroy() {
|
|
7905
|
+
this.overlayRef().nativeElement.remove();
|
|
7906
|
+
}
|
|
7907
|
+
dismiss() {
|
|
7908
|
+
this.open.set(false);
|
|
7909
|
+
}
|
|
7910
|
+
onBackdropClick() {
|
|
7911
|
+
if (this.closeOnBackdropClick()) {
|
|
7912
|
+
this.dismiss();
|
|
7913
|
+
}
|
|
7914
|
+
}
|
|
7915
|
+
onKeydown(event) {
|
|
7916
|
+
if (event.key === 'Escape' && this.closeOnEscape() && this.open()) {
|
|
7917
|
+
event.stopPropagation();
|
|
7918
|
+
this.dismiss();
|
|
7919
|
+
}
|
|
7920
|
+
}
|
|
7921
|
+
onTransitionEnd(event) {
|
|
7922
|
+
if (event.propertyName !== 'transform' || event.target !== event.currentTarget) {
|
|
7923
|
+
return;
|
|
7924
|
+
}
|
|
7925
|
+
if (this.open()) {
|
|
7926
|
+
this.opened.emit();
|
|
7927
|
+
}
|
|
7928
|
+
else {
|
|
7929
|
+
this.closed.emit();
|
|
7930
|
+
this.restoreFocus();
|
|
7931
|
+
}
|
|
7932
|
+
}
|
|
7933
|
+
restoreFocus() {
|
|
7934
|
+
if (this.previouslyFocusedElement && typeof this.previouslyFocusedElement.focus === 'function') {
|
|
7935
|
+
this.previouslyFocusedElement.focus();
|
|
7936
|
+
this.previouslyFocusedElement = null;
|
|
7937
|
+
}
|
|
7938
|
+
}
|
|
7939
|
+
registerMdiIcons() {
|
|
7940
|
+
const mdiIcons = {
|
|
7941
|
+
'close': mdiClose,
|
|
7942
|
+
};
|
|
7943
|
+
this.iconRegistry.registerLibrary({
|
|
7944
|
+
name: 'mdi',
|
|
7945
|
+
resolver: (iconName) => {
|
|
7946
|
+
const pathData = mdiIcons[iconName];
|
|
7947
|
+
if (!pathData) {
|
|
7948
|
+
return null;
|
|
7949
|
+
}
|
|
7950
|
+
return `<svg viewBox="0 0 24 24"><path fill="currentColor" d="${pathData}"/></svg>`;
|
|
7951
|
+
},
|
|
7952
|
+
});
|
|
7953
|
+
}
|
|
7954
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnSidePanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7955
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnSidePanelComponent, isStandalone: true, selector: "tn-side-panel", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, hasBackdrop: { classPropertyName: "hasBackdrop", publicName: "hasBackdrop", isSignal: true, isRequired: false, transformFunction: null }, closeOnBackdropClick: { classPropertyName: "closeOnBackdropClick", publicName: "closeOnBackdropClick", isSignal: true, isRequired: false, transformFunction: null }, closeOnEscape: { classPropertyName: "closeOnEscape", publicName: "closeOnEscape", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", opened: "opened", closed: "closed" }, host: { properties: { "attr.data-tn-panel": "panelId" }, classAttribute: "tn-side-panel" }, queries: [{ propertyName: "actionContent", predicate: TnSidePanelActionDirective, isSignal: true }], viewQueries: [{ propertyName: "overlayRef", first: true, predicate: ["overlay"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Overlay wrapper: portaled to document.body -->\n<div\n #overlay\n class=\"tn-side-panel__overlay\"\n role=\"dialog\"\n [attr.data-tn-panel]=\"panelId\"\n [class.tn-side-panel__overlay--initialized]=\"initialized()\"\n [class.tn-side-panel__overlay--open]=\"open()\"\n [attr.aria-modal]=\"open() ? 'true' : null\"\n [attr.aria-labelledby]=\"open() ? titleId : null\"\n [attr.aria-hidden]=\"!open() ? 'true' : null\">\n\n <!-- Backdrop -->\n @if (hasBackdrop()) {\n <div\n class=\"tn-side-panel__backdrop\"\n aria-hidden=\"true\"\n (click)=\"onBackdropClick()\">\n </div>\n }\n\n <!-- Panel -->\n <div\n class=\"tn-side-panel__panel\"\n tabindex=\"-1\"\n cdkTrapFocus\n [style.width]=\"width()\"\n [cdkTrapFocusAutoCapture]=\"open()\"\n (transitionend)=\"onTransitionEnd($event)\"\n (keydown)=\"onKeydown($event)\">\n\n <!-- Header -->\n <header class=\"tn-side-panel__header\">\n <h2 class=\"tn-side-panel__title\" [id]=\"titleId\">{{ title() }}</h2>\n <div class=\"tn-side-panel__header-actions\">\n <ng-content select=\"[tnSidePanelHeaderAction]\" />\n <tn-icon-button\n name=\"close\"\n library=\"mdi\"\n size=\"sm\"\n ariaLabel=\"Dismiss\"\n (onClick)=\"dismiss()\" />\n </div>\n </header>\n\n <!-- Content -->\n <section class=\"tn-side-panel__content\">\n <ng-content />\n </section>\n\n <!-- Actions -->\n @if (hasActions()) {\n <footer class=\"tn-side-panel__actions\">\n <ng-content select=\"[tnSidePanelAction]\" />\n </footer>\n }\n </div>\n</div>\n", styles: [":host{display:contents}.tn-side-panel__overlay{position:fixed;inset:0;z-index:1000;pointer-events:none}.tn-side-panel__overlay--open{pointer-events:auto}.tn-side-panel__overlay--open .tn-side-panel__backdrop{opacity:1}.tn-side-panel__overlay--open .tn-side-panel__panel{transform:translate(0)}.tn-side-panel__backdrop{position:absolute;inset:0;background:#00000080;opacity:0}.tn-side-panel__overlay--initialized .tn-side-panel__backdrop{transition:opacity .2s ease}.tn-side-panel__panel{position:absolute;top:0;right:0;bottom:0;display:flex;flex-direction:column;max-width:100vw;background:var(--tn-bg2, #282828);color:var(--tn-fg1, #ffffff);box-shadow:-4px 0 24px #0000004d;outline:none;transform:translate(100%)}.tn-side-panel__overlay--initialized .tn-side-panel__panel{transition:transform .3s cubic-bezier(.4,0,.2,1)}.tn-side-panel__header{flex:0 0 auto;display:flex;align-items:center;gap:16px;padding:16px 24px;border-bottom:1px solid var(--tn-lines, #383838)}.tn-side-panel__title{margin:0;font-size:1.25rem;font-weight:600;line-height:1.5;color:var(--tn-fg1, #ffffff);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tn-side-panel__header-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}.tn-side-panel__content{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;padding:var(--tn-content-padding, 24px);-webkit-overflow-scrolling:touch}.tn-side-panel__actions{flex:0 0 auto;display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--tn-lines, #383838)}@media(max-width:640px){.tn-side-panel__panel{width:100vw!important}}@media(prefers-reduced-motion:reduce){.tn-side-panel__panel,.tn-side-panel__backdrop{transition-duration:0ms!important}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: A11yModule }, { kind: "directive", type: i1$4.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: TnIconButtonComponent, selector: "tn-icon-button", inputs: ["disabled", "ariaLabel", "name", "size", "color", "tooltip", "library"], outputs: ["onClick"] }] });
|
|
7956
|
+
}
|
|
7957
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnSidePanelComponent, decorators: [{
|
|
7958
|
+
type: Component,
|
|
7959
|
+
args: [{ selector: 'tn-side-panel', standalone: true, imports: [CommonModule, A11yModule, TnIconButtonComponent], host: {
|
|
7960
|
+
'class': 'tn-side-panel',
|
|
7961
|
+
'[attr.data-tn-panel]': 'panelId',
|
|
7962
|
+
}, template: "<!-- Overlay wrapper: portaled to document.body -->\n<div\n #overlay\n class=\"tn-side-panel__overlay\"\n role=\"dialog\"\n [attr.data-tn-panel]=\"panelId\"\n [class.tn-side-panel__overlay--initialized]=\"initialized()\"\n [class.tn-side-panel__overlay--open]=\"open()\"\n [attr.aria-modal]=\"open() ? 'true' : null\"\n [attr.aria-labelledby]=\"open() ? titleId : null\"\n [attr.aria-hidden]=\"!open() ? 'true' : null\">\n\n <!-- Backdrop -->\n @if (hasBackdrop()) {\n <div\n class=\"tn-side-panel__backdrop\"\n aria-hidden=\"true\"\n (click)=\"onBackdropClick()\">\n </div>\n }\n\n <!-- Panel -->\n <div\n class=\"tn-side-panel__panel\"\n tabindex=\"-1\"\n cdkTrapFocus\n [style.width]=\"width()\"\n [cdkTrapFocusAutoCapture]=\"open()\"\n (transitionend)=\"onTransitionEnd($event)\"\n (keydown)=\"onKeydown($event)\">\n\n <!-- Header -->\n <header class=\"tn-side-panel__header\">\n <h2 class=\"tn-side-panel__title\" [id]=\"titleId\">{{ title() }}</h2>\n <div class=\"tn-side-panel__header-actions\">\n <ng-content select=\"[tnSidePanelHeaderAction]\" />\n <tn-icon-button\n name=\"close\"\n library=\"mdi\"\n size=\"sm\"\n ariaLabel=\"Dismiss\"\n (onClick)=\"dismiss()\" />\n </div>\n </header>\n\n <!-- Content -->\n <section class=\"tn-side-panel__content\">\n <ng-content />\n </section>\n\n <!-- Actions -->\n @if (hasActions()) {\n <footer class=\"tn-side-panel__actions\">\n <ng-content select=\"[tnSidePanelAction]\" />\n </footer>\n }\n </div>\n</div>\n", styles: [":host{display:contents}.tn-side-panel__overlay{position:fixed;inset:0;z-index:1000;pointer-events:none}.tn-side-panel__overlay--open{pointer-events:auto}.tn-side-panel__overlay--open .tn-side-panel__backdrop{opacity:1}.tn-side-panel__overlay--open .tn-side-panel__panel{transform:translate(0)}.tn-side-panel__backdrop{position:absolute;inset:0;background:#00000080;opacity:0}.tn-side-panel__overlay--initialized .tn-side-panel__backdrop{transition:opacity .2s ease}.tn-side-panel__panel{position:absolute;top:0;right:0;bottom:0;display:flex;flex-direction:column;max-width:100vw;background:var(--tn-bg2, #282828);color:var(--tn-fg1, #ffffff);box-shadow:-4px 0 24px #0000004d;outline:none;transform:translate(100%)}.tn-side-panel__overlay--initialized .tn-side-panel__panel{transition:transform .3s cubic-bezier(.4,0,.2,1)}.tn-side-panel__header{flex:0 0 auto;display:flex;align-items:center;gap:16px;padding:16px 24px;border-bottom:1px solid var(--tn-lines, #383838)}.tn-side-panel__title{margin:0;font-size:1.25rem;font-weight:600;line-height:1.5;color:var(--tn-fg1, #ffffff);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tn-side-panel__header-actions{display:flex;align-items:center;gap:8px;flex-shrink:0}.tn-side-panel__content{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;padding:var(--tn-content-padding, 24px);-webkit-overflow-scrolling:touch}.tn-side-panel__actions{flex:0 0 auto;display:flex;justify-content:flex-end;gap:12px;padding:16px 24px;border-top:1px solid var(--tn-lines, #383838)}@media(max-width:640px){.tn-side-panel__panel{width:100vw!important}}@media(prefers-reduced-motion:reduce){.tn-side-panel__panel,.tn-side-panel__backdrop{transition-duration:0ms!important}}\n"] }]
|
|
7963
|
+
}], ctorParameters: () => [], propDecorators: { overlayRef: [{ type: i0.ViewChild, args: ['overlay', { isSignal: true }] }], open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], hasBackdrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasBackdrop", required: false }] }], closeOnBackdropClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnBackdropClick", required: false }] }], closeOnEscape: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnEscape", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], actionContent: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TnSidePanelActionDirective), { isSignal: true }] }] } });
|
|
7964
|
+
|
|
7965
|
+
/**
|
|
7966
|
+
* Harness for interacting with `TnSidePanelComponent` in tests.
|
|
7967
|
+
*
|
|
7968
|
+
* @example
|
|
7969
|
+
* ```typescript
|
|
7970
|
+
* const panel = await loader.getHarness(TnSidePanelHarness);
|
|
7971
|
+
* expect(await panel.isOpen()).toBe(true);
|
|
7972
|
+
* expect(await panel.getTitle()).toBe('Edit User');
|
|
7973
|
+
* await panel.dismiss();
|
|
7974
|
+
* ```
|
|
7975
|
+
*/
|
|
7976
|
+
class TnSidePanelHarness extends ComponentHarness {
|
|
7977
|
+
static hostSelector = 'tn-side-panel';
|
|
7978
|
+
static with(options = {}) {
|
|
7979
|
+
return new HarnessPredicate(TnSidePanelHarness, options)
|
|
7980
|
+
.addOption('title', options.title, (harness, title) => HarnessPredicate.stringMatches(harness.getTitle(), title));
|
|
7981
|
+
}
|
|
7982
|
+
/**
|
|
7983
|
+
* Locate the overlay wrapper, which may be portaled to document.body.
|
|
7984
|
+
* Uses the data-tn-panel attribute to correlate the host with its overlay.
|
|
7985
|
+
*/
|
|
7986
|
+
async getOverlay() {
|
|
7987
|
+
const host = await this.host();
|
|
7988
|
+
const panelId = await host.getAttribute('data-tn-panel');
|
|
7989
|
+
return this.documentRootLocatorFactory().locatorFor(`[data-tn-panel="${panelId}"].tn-side-panel__overlay`)();
|
|
7990
|
+
}
|
|
7991
|
+
/** Get the panel title text. */
|
|
7992
|
+
async getTitle() {
|
|
7993
|
+
const host = await this.host();
|
|
7994
|
+
const panelId = await host.getAttribute('data-tn-panel');
|
|
7995
|
+
const titleEl = await this.documentRootLocatorFactory().locatorFor(`[data-tn-panel="${panelId}"] .tn-side-panel__title`)();
|
|
7996
|
+
return (await titleEl.text()).trim();
|
|
7997
|
+
}
|
|
7998
|
+
/** Whether the panel is currently open. */
|
|
7999
|
+
async isOpen() {
|
|
8000
|
+
const overlay = await this.getOverlay();
|
|
8001
|
+
return overlay.hasClass('tn-side-panel__overlay--open');
|
|
8002
|
+
}
|
|
8003
|
+
/** Click the dismiss button to close the panel. */
|
|
8004
|
+
async dismiss() {
|
|
8005
|
+
const host = await this.host();
|
|
8006
|
+
const panelId = await host.getAttribute('data-tn-panel');
|
|
8007
|
+
const button = await this.documentRootLocatorFactory().locatorFor(`[data-tn-panel="${panelId}"] .tn-side-panel__header-actions tn-icon-button`)();
|
|
8008
|
+
await button.click();
|
|
8009
|
+
}
|
|
8010
|
+
/** Get the text content of the scrollable body area. */
|
|
8011
|
+
async getContentText() {
|
|
8012
|
+
const host = await this.host();
|
|
8013
|
+
const panelId = await host.getAttribute('data-tn-panel');
|
|
8014
|
+
const content = await this.documentRootLocatorFactory().locatorFor(`[data-tn-panel="${panelId}"] .tn-side-panel__content`)();
|
|
8015
|
+
return (await content.text()).trim();
|
|
8016
|
+
}
|
|
8017
|
+
}
|
|
8018
|
+
|
|
7823
8019
|
class TnStepComponent {
|
|
7824
8020
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
7825
8021
|
icon = input(undefined, ...(ngDevMode ? [{ debugName: "icon" }] : []));
|
|
@@ -9309,5 +9505,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
9309
9505
|
* Generated bundle index. Do not edit.
|
|
9310
9506
|
*/
|
|
9311
9507
|
|
|
9312
|
-
export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, StripMntPrefixPipe, THEME_MAP, THEME_STORAGE_KEY, TN_THEME_DEFINITIONS, TnBannerActionDirective, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnCalendarComponent, TnCalendarHeaderComponent, TnCardComponent, TnCellDefDirective, TnCheckboxComponent, TnChipComponent, TnConfirmDialogComponent, TnDateInputComponent, TnDateRangeInputComponent, TnDialog, TnDialogShellComponent, TnDividerComponent, TnDividerDirective, TnExpansionPanelComponent, TnFilePickerComponent, TnFilePickerPopupComponent, TnFormFieldComponent, TnHeaderCellDefDirective, TnIconButtonComponent, TnIconButtonHarness, TnIconComponent, TnIconHarness, TnIconRegistryService, TnIconTesting, TnInputComponent, TnInputDirective, TnInputHarness, TnKeyboardShortcutComponent, TnKeyboardShortcutService, TnListAvatarDirective, TnListComponent, TnListIconDirective, TnListItemComponent, TnListItemLineDirective, TnListItemPrimaryDirective, TnListItemSecondaryDirective, TnListItemTitleDirective, TnListItemTrailingDirective, TnListOptionComponent, TnListSubheaderComponent, TnMenuComponent, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSlideToggleComponent, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnTabComponent, TnTabHarness, TnTabPanelComponent, TnTabPanelHarness, TnTableColumnDirective, TnTableComponent, TnTabsComponent, TnTabsHarness, TnTheme, TnThemeService, TnTimeInputComponent, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeNodeComponent, TnTreeNodeOutletDirective, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, createLucideLibrary, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, libIconMarker, registerLucideIcons, setupLucideIntegration, tnIconMarker };
|
|
9508
|
+
export { CommonShortcuts, DEFAULT_THEME, DiskIconComponent, DiskType, FileSizePipe, InputType, LinuxModifierKeys, LinuxShortcuts, ModifierKeys, QuickShortcuts, ShortcutBuilder, StripMntPrefixPipe, THEME_MAP, THEME_STORAGE_KEY, TN_THEME_DEFINITIONS, TnBannerActionDirective, TnBannerComponent, TnBannerHarness, TnBrandedSpinnerComponent, TnButtonComponent, TnButtonHarness, TnButtonToggleComponent, TnButtonToggleGroupComponent, TnCalendarComponent, TnCalendarHeaderComponent, TnCardComponent, TnCellDefDirective, TnCheckboxComponent, TnChipComponent, TnConfirmDialogComponent, TnDateInputComponent, TnDateRangeInputComponent, TnDialog, TnDialogShellComponent, TnDividerComponent, TnDividerDirective, TnExpansionPanelComponent, TnFilePickerComponent, TnFilePickerPopupComponent, TnFormFieldComponent, TnHeaderCellDefDirective, TnIconButtonComponent, TnIconButtonHarness, TnIconComponent, TnIconHarness, TnIconRegistryService, TnIconTesting, TnInputComponent, TnInputDirective, TnInputHarness, TnKeyboardShortcutComponent, TnKeyboardShortcutService, TnListAvatarDirective, TnListComponent, TnListIconDirective, TnListItemComponent, TnListItemLineDirective, TnListItemPrimaryDirective, TnListItemSecondaryDirective, TnListItemTitleDirective, TnListItemTrailingDirective, TnListOptionComponent, TnListSubheaderComponent, TnMenuComponent, TnMenuTriggerDirective, TnMonthViewComponent, TnMultiYearViewComponent, TnNestedTreeNodeComponent, TnParticleProgressBarComponent, TnProgressBarComponent, TnRadioComponent, TnSelectComponent, TnSelectHarness, TnSelectionListComponent, TnSidePanelActionDirective, TnSidePanelComponent, TnSidePanelHarness, TnSidePanelHeaderActionDirective, TnSlideToggleComponent, TnSliderComponent, TnSliderThumbDirective, TnSliderWithLabelDirective, TnSpinnerComponent, TnSpriteLoaderService, TnStepComponent, TnStepperComponent, TnTabComponent, TnTabHarness, TnTabPanelComponent, TnTabPanelHarness, TnTableColumnDirective, TnTableComponent, TnTabsComponent, TnTabsHarness, TnTheme, TnThemeService, TnTimeInputComponent, TnTooltipComponent, TnTooltipDirective, TnTreeComponent, TnTreeFlatDataSource, TnTreeFlattener, TnTreeNodeComponent, TnTreeNodeOutletDirective, TruncatePathPipe, WindowsModifierKeys, WindowsShortcuts, createLucideLibrary, createShortcut, defaultSpriteBasePath, defaultSpriteConfigPath, libIconMarker, registerLucideIcons, setupLucideIntegration, tnIconMarker };
|
|
9313
9509
|
//# sourceMappingURL=truenas-ui-components.mjs.map
|