@truenas/ui-components 0.7.2 → 0.7.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.
|
@@ -25801,14 +25801,14 @@ class TnSidePanelComponent {
|
|
|
25801
25801
|
});
|
|
25802
25802
|
}
|
|
25803
25803
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnSidePanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
25804
|
-
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 }, closeGuard: { classPropertyName: "closeGuard", publicName: "closeGuard", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null }, closeButtonTestId: { classPropertyName: "closeButtonTestId", publicName: "closeButtonTestId", isSignal: true, isRequired: false, transformFunction: null }, closeButtonAriaLabel: { classPropertyName: "closeButtonAriaLabel", publicName: "closeButtonAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, contentAriaLabel: { classPropertyName: "contentAriaLabel", publicName: "contentAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "ariaLabelledby", 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 }, { propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }, { propertyName: "contentRef", first: true, predicate: ["content"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\n Overlay wrapper: portaled to document.body.\n\n A CLOSED panel is `inert` as well as `aria-hidden` (#214). It stays in the DOM\n and keeps its close button and its projected content, so `aria-hidden` alone\n hid a subtree a keyboard user could still Tab into \u2014 landing focus on controls\n that are translated off-screen. `inert` takes the subtree out of the focus\n order and the accessibility tree together; `aria-hidden` stays beside it for\n browsers without `inert` (Firefox before 112), where it is still the half that\n works. Same reasoning as the checkbox in `list-option.component.html`.\n\n `aria-label` and `aria-labelledby` are gated on `open()` for the same reason\n `aria-modal` is: a closed panel is not in the accessibility tree, so a name on\n it would describe nothing. `resolvedAriaLabelledby` prefers the visible\n heading. `resolvedAriaLabel` is `null` when the panel is named by a heading or\n an IDREF and the caller passed no `ariaLabel` of their own \u2014 an explicit one is\n always emitted, so that a dangling IDREF cannot leave the panel unnamed.\n-->\n<div\n #overlay\n class=\"tn-side-panel__overlay\"\n role=\"dialog\"\n tnTestIdType=\"side-panel\"\n [attr.data-tn-panel]=\"panelId\"\n [tnTestId]=\"testId()\"\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() ? resolvedAriaLabelledby() : null\"\n [attr.aria-label]=\"open() ? resolvedAriaLabel() : null\"\n [attr.aria-hidden]=\"!open() ? 'true' : null\"\n [attr.inert]=\"open() ? 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 <!--\n Panel. `cdkTrapFocus` keeps Tab inside it while it is open; what moves focus\n IN on open is `tnFocusOnOpen` in the component, not\n `[cdkTrapFocusAutoCapture]`, which used to be here and could silently do\n nothing (#227). `tabindex=\"-1\"` is what makes this element the target it\n focuses \u2014 see `../a11y/initial-focus.ts` for why the container and not the\n first control inside it.\n -->\n <div\n #panel\n class=\"tn-side-panel__panel\"\n tabindex=\"-1\"\n cdkTrapFocus\n [style.width]=\"width()\"\n (transitionend)=\"onTransitionEnd($event)\"\n (keydown)=\"onKeydown($event)\">\n\n <!-- Header -->\n <header class=\"tn-side-panel__header\">\n <!--\n No heading element at all when there is no title, rather than an empty\n one: an `<h2>` with no text is an `empty-heading` violation, and it puts\n a level-2 heading with nothing in it into the document outline.\n -->\n @if (hasTitle()) {\n <h2 class=\"tn-side-panel__title\" [id]=\"titleId\">{{ title() }}</h2>\n }\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]=\"closeButtonAriaLabel()\"\n [testId]=\"closeButtonTestId()\"\n (onClick)=\"dismiss()\" />\n </div>\n </header>\n\n <!--\n Content. This is the element that scrolls, and a scrolling element a\n keyboard cannot reach is content below the fold that a keyboard cannot\n read (#248). The panel's own `tabindex=\"-1\"` above does not cover it: that\n is a focus TARGET, not a tab stop, and it is on the container rather than\n on the element with the overflow.\n\n All three attributes are gated together, and the gate is the point \u2014 an\n unconditional tab stop would land on every panel in the library, including\n the ones whose content fits, where it announces a group and does nothing.\n\n The gate is `contentKeyboardReachable`, which is the measurement OR the\n region's own focus, not the measurement alone. Content that stops\n overflowing while the region is focused would otherwise take the tab stop\n off the focused element and blur a keyboard user out of the open panel.\n Both halves are `tnScrollableRegion`'s, in `../a11y/scrollable-region.ts`,\n which says why in full \u2014 including why it listens for this element's own\n `focus`/`blur` itself rather than leaving each caller to bind them.\n\n `role=\"group\"` rather than the `region` a named `<section>` would imply:\n `region` is a landmark, and a landmark named the same thing in every panel\n is what `landmark-unique` reports the moment two of them are open. A group\n is not summarised, which is what this is.\n -->\n <section\n #content\n class=\"tn-side-panel__content\"\n [attr.tabindex]=\"contentKeyboardReachable() ? '0' : null\"\n [attr.role]=\"contentKeyboardReachable() ? 'group' : null\"\n [attr.aria-label]=\"contentKeyboardReachable() ? contentAriaLabel() : null\">\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);box-shadow:-4px 0 24px #0000004d}.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 #0000;outline:none;transform:translate(100%)}.tn-side-panel__overlay--initialized .tn-side-panel__panel{transition:transform .3s cubic-bezier(.4,0,.2,1),box-shadow .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;margin-left:auto}.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.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: TnIconButtonComponent, selector: "tn-icon-button", inputs: ["disabled", "dense", "ariaLabel", "ariaExpanded", "testId", "name", "size", "color", "tooltip", "tooltipPosition", "tooltipSticky", "library", "iconClass"], outputs: ["onClick"] }, { kind: "directive", type: TnTestIdDirective, selector: "[tnTestId]", inputs: ["tnTestId", "tnTestIdType"] }] });
|
|
25804
|
+
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 }, closeGuard: { classPropertyName: "closeGuard", publicName: "closeGuard", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null }, closeButtonTestId: { classPropertyName: "closeButtonTestId", publicName: "closeButtonTestId", isSignal: true, isRequired: false, transformFunction: null }, closeButtonAriaLabel: { classPropertyName: "closeButtonAriaLabel", publicName: "closeButtonAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, contentAriaLabel: { classPropertyName: "contentAriaLabel", publicName: "contentAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "ariaLabelledby", 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 }, { propertyName: "panelRef", first: true, predicate: ["panel"], descendants: true, isSignal: true }, { propertyName: "contentRef", first: true, predicate: ["content"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\n Overlay wrapper: portaled to document.body.\n\n A CLOSED panel is `inert` as well as `aria-hidden` (#214). It stays in the DOM\n and keeps its close button and its projected content, so `aria-hidden` alone\n hid a subtree a keyboard user could still Tab into \u2014 landing focus on controls\n that are translated off-screen. `inert` takes the subtree out of the focus\n order and the accessibility tree together; `aria-hidden` stays beside it for\n browsers without `inert` (Firefox before 112), where it is still the half that\n works. Same reasoning as the checkbox in `list-option.component.html`.\n\n `aria-label` and `aria-labelledby` are gated on `open()` for the same reason\n `aria-modal` is: a closed panel is not in the accessibility tree, so a name on\n it would describe nothing. `resolvedAriaLabelledby` prefers the visible\n heading. `resolvedAriaLabel` is `null` when the panel is named by a heading or\n an IDREF and the caller passed no `ariaLabel` of their own \u2014 an explicit one is\n always emitted, so that a dangling IDREF cannot leave the panel unnamed.\n-->\n<div\n #overlay\n class=\"tn-side-panel__overlay\"\n role=\"dialog\"\n tnTestIdType=\"side-panel\"\n [attr.data-tn-panel]=\"panelId\"\n [tnTestId]=\"testId()\"\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() ? resolvedAriaLabelledby() : null\"\n [attr.aria-label]=\"open() ? resolvedAriaLabel() : null\"\n [attr.aria-hidden]=\"!open() ? 'true' : null\"\n [attr.inert]=\"open() ? 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 <!--\n Panel. `cdkTrapFocus` keeps Tab inside it while it is open; what moves focus\n IN on open is `tnFocusOnOpen` in the component, not\n `[cdkTrapFocusAutoCapture]`, which used to be here and could silently do\n nothing (#227). `tabindex=\"-1\"` is what makes this element the target it\n focuses \u2014 see `../a11y/initial-focus.ts` for why the container and not the\n first control inside it.\n -->\n <div\n #panel\n class=\"tn-side-panel__panel\"\n tabindex=\"-1\"\n cdkTrapFocus\n [style.width]=\"width()\"\n (transitionend)=\"onTransitionEnd($event)\"\n (keydown)=\"onKeydown($event)\">\n\n <!-- Header -->\n <header class=\"tn-side-panel__header\">\n <!--\n No heading element at all when there is no title, rather than an empty\n one: an `<h2>` with no text is an `empty-heading` violation, and it puts\n a level-2 heading with nothing in it into the document outline.\n -->\n @if (hasTitle()) {\n <h2 class=\"tn-side-panel__title\" [id]=\"titleId\">{{ title() }}</h2>\n }\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]=\"closeButtonAriaLabel()\"\n [testId]=\"closeButtonTestId()\"\n (onClick)=\"dismiss()\" />\n </div>\n </header>\n\n <!--\n Content. This is the element that scrolls, and a scrolling element a\n keyboard cannot reach is content below the fold that a keyboard cannot\n read (#248). The panel's own `tabindex=\"-1\"` above does not cover it: that\n is a focus TARGET, not a tab stop, and it is on the container rather than\n on the element with the overflow.\n\n All three attributes are gated together, and the gate is the point \u2014 an\n unconditional tab stop would land on every panel in the library, including\n the ones whose content fits, where it announces a group and does nothing.\n\n The gate is `contentKeyboardReachable`, which is the measurement OR the\n region's own focus, not the measurement alone. Content that stops\n overflowing while the region is focused would otherwise take the tab stop\n off the focused element and blur a keyboard user out of the open panel.\n Both halves are `tnScrollableRegion`'s, in `../a11y/scrollable-region.ts`,\n which says why in full \u2014 including why it listens for this element's own\n `focus`/`blur` itself rather than leaving each caller to bind them.\n\n `role=\"group\"` rather than the `region` a named `<section>` would imply:\n `region` is a landmark, and a landmark named the same thing in every panel\n is what `landmark-unique` reports the moment two of them are open. A group\n is not summarised, which is what this is.\n -->\n <section\n #content\n class=\"tn-side-panel__content\"\n [attr.tabindex]=\"contentKeyboardReachable() ? '0' : null\"\n [attr.role]=\"contentKeyboardReachable() ? 'group' : null\"\n [attr.aria-label]=\"contentKeyboardReachable() ? contentAriaLabel() : null\">\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);box-shadow:-4px 0 24px #0000004d}.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 #0000;outline:none;transform:translate(100%)}.tn-side-panel__overlay--initialized .tn-side-panel__panel{transition:transform .3s cubic-bezier(.4,0,.2,1),box-shadow .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;margin-left:auto}.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;overflow-wrap:break-word}.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.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "component", type: TnIconButtonComponent, selector: "tn-icon-button", inputs: ["disabled", "dense", "ariaLabel", "ariaExpanded", "testId", "name", "size", "color", "tooltip", "tooltipPosition", "tooltipSticky", "library", "iconClass"], outputs: ["onClick"] }, { kind: "directive", type: TnTestIdDirective, selector: "[tnTestId]", inputs: ["tnTestId", "tnTestIdType"] }] });
|
|
25805
25805
|
}
|
|
25806
25806
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnSidePanelComponent, decorators: [{
|
|
25807
25807
|
type: Component,
|
|
25808
25808
|
args: [{ selector: 'tn-side-panel', standalone: true, imports: [CommonModule, A11yModule, TnIconButtonComponent, TnTestIdDirective], host: {
|
|
25809
25809
|
'class': 'tn-side-panel',
|
|
25810
25810
|
'[attr.data-tn-panel]': 'panelId',
|
|
25811
|
-
}, template: "<!--\n Overlay wrapper: portaled to document.body.\n\n A CLOSED panel is `inert` as well as `aria-hidden` (#214). It stays in the DOM\n and keeps its close button and its projected content, so `aria-hidden` alone\n hid a subtree a keyboard user could still Tab into \u2014 landing focus on controls\n that are translated off-screen. `inert` takes the subtree out of the focus\n order and the accessibility tree together; `aria-hidden` stays beside it for\n browsers without `inert` (Firefox before 112), where it is still the half that\n works. Same reasoning as the checkbox in `list-option.component.html`.\n\n `aria-label` and `aria-labelledby` are gated on `open()` for the same reason\n `aria-modal` is: a closed panel is not in the accessibility tree, so a name on\n it would describe nothing. `resolvedAriaLabelledby` prefers the visible\n heading. `resolvedAriaLabel` is `null` when the panel is named by a heading or\n an IDREF and the caller passed no `ariaLabel` of their own \u2014 an explicit one is\n always emitted, so that a dangling IDREF cannot leave the panel unnamed.\n-->\n<div\n #overlay\n class=\"tn-side-panel__overlay\"\n role=\"dialog\"\n tnTestIdType=\"side-panel\"\n [attr.data-tn-panel]=\"panelId\"\n [tnTestId]=\"testId()\"\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() ? resolvedAriaLabelledby() : null\"\n [attr.aria-label]=\"open() ? resolvedAriaLabel() : null\"\n [attr.aria-hidden]=\"!open() ? 'true' : null\"\n [attr.inert]=\"open() ? 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 <!--\n Panel. `cdkTrapFocus` keeps Tab inside it while it is open; what moves focus\n IN on open is `tnFocusOnOpen` in the component, not\n `[cdkTrapFocusAutoCapture]`, which used to be here and could silently do\n nothing (#227). `tabindex=\"-1\"` is what makes this element the target it\n focuses \u2014 see `../a11y/initial-focus.ts` for why the container and not the\n first control inside it.\n -->\n <div\n #panel\n class=\"tn-side-panel__panel\"\n tabindex=\"-1\"\n cdkTrapFocus\n [style.width]=\"width()\"\n (transitionend)=\"onTransitionEnd($event)\"\n (keydown)=\"onKeydown($event)\">\n\n <!-- Header -->\n <header class=\"tn-side-panel__header\">\n <!--\n No heading element at all when there is no title, rather than an empty\n one: an `<h2>` with no text is an `empty-heading` violation, and it puts\n a level-2 heading with nothing in it into the document outline.\n -->\n @if (hasTitle()) {\n <h2 class=\"tn-side-panel__title\" [id]=\"titleId\">{{ title() }}</h2>\n }\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]=\"closeButtonAriaLabel()\"\n [testId]=\"closeButtonTestId()\"\n (onClick)=\"dismiss()\" />\n </div>\n </header>\n\n <!--\n Content. This is the element that scrolls, and a scrolling element a\n keyboard cannot reach is content below the fold that a keyboard cannot\n read (#248). The panel's own `tabindex=\"-1\"` above does not cover it: that\n is a focus TARGET, not a tab stop, and it is on the container rather than\n on the element with the overflow.\n\n All three attributes are gated together, and the gate is the point \u2014 an\n unconditional tab stop would land on every panel in the library, including\n the ones whose content fits, where it announces a group and does nothing.\n\n The gate is `contentKeyboardReachable`, which is the measurement OR the\n region's own focus, not the measurement alone. Content that stops\n overflowing while the region is focused would otherwise take the tab stop\n off the focused element and blur a keyboard user out of the open panel.\n Both halves are `tnScrollableRegion`'s, in `../a11y/scrollable-region.ts`,\n which says why in full \u2014 including why it listens for this element's own\n `focus`/`blur` itself rather than leaving each caller to bind them.\n\n `role=\"group\"` rather than the `region` a named `<section>` would imply:\n `region` is a landmark, and a landmark named the same thing in every panel\n is what `landmark-unique` reports the moment two of them are open. A group\n is not summarised, which is what this is.\n -->\n <section\n #content\n class=\"tn-side-panel__content\"\n [attr.tabindex]=\"contentKeyboardReachable() ? '0' : null\"\n [attr.role]=\"contentKeyboardReachable() ? 'group' : null\"\n [attr.aria-label]=\"contentKeyboardReachable() ? contentAriaLabel() : null\">\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);box-shadow:-4px 0 24px #0000004d}.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 #0000;outline:none;transform:translate(100%)}.tn-side-panel__overlay--initialized .tn-side-panel__panel{transition:transform .3s cubic-bezier(.4,0,.2,1),box-shadow .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;margin-left:auto}.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"] }]
|
|
25811
|
+
}, template: "<!--\n Overlay wrapper: portaled to document.body.\n\n A CLOSED panel is `inert` as well as `aria-hidden` (#214). It stays in the DOM\n and keeps its close button and its projected content, so `aria-hidden` alone\n hid a subtree a keyboard user could still Tab into \u2014 landing focus on controls\n that are translated off-screen. `inert` takes the subtree out of the focus\n order and the accessibility tree together; `aria-hidden` stays beside it for\n browsers without `inert` (Firefox before 112), where it is still the half that\n works. Same reasoning as the checkbox in `list-option.component.html`.\n\n `aria-label` and `aria-labelledby` are gated on `open()` for the same reason\n `aria-modal` is: a closed panel is not in the accessibility tree, so a name on\n it would describe nothing. `resolvedAriaLabelledby` prefers the visible\n heading. `resolvedAriaLabel` is `null` when the panel is named by a heading or\n an IDREF and the caller passed no `ariaLabel` of their own \u2014 an explicit one is\n always emitted, so that a dangling IDREF cannot leave the panel unnamed.\n-->\n<div\n #overlay\n class=\"tn-side-panel__overlay\"\n role=\"dialog\"\n tnTestIdType=\"side-panel\"\n [attr.data-tn-panel]=\"panelId\"\n [tnTestId]=\"testId()\"\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() ? resolvedAriaLabelledby() : null\"\n [attr.aria-label]=\"open() ? resolvedAriaLabel() : null\"\n [attr.aria-hidden]=\"!open() ? 'true' : null\"\n [attr.inert]=\"open() ? 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 <!--\n Panel. `cdkTrapFocus` keeps Tab inside it while it is open; what moves focus\n IN on open is `tnFocusOnOpen` in the component, not\n `[cdkTrapFocusAutoCapture]`, which used to be here and could silently do\n nothing (#227). `tabindex=\"-1\"` is what makes this element the target it\n focuses \u2014 see `../a11y/initial-focus.ts` for why the container and not the\n first control inside it.\n -->\n <div\n #panel\n class=\"tn-side-panel__panel\"\n tabindex=\"-1\"\n cdkTrapFocus\n [style.width]=\"width()\"\n (transitionend)=\"onTransitionEnd($event)\"\n (keydown)=\"onKeydown($event)\">\n\n <!-- Header -->\n <header class=\"tn-side-panel__header\">\n <!--\n No heading element at all when there is no title, rather than an empty\n one: an `<h2>` with no text is an `empty-heading` violation, and it puts\n a level-2 heading with nothing in it into the document outline.\n -->\n @if (hasTitle()) {\n <h2 class=\"tn-side-panel__title\" [id]=\"titleId\">{{ title() }}</h2>\n }\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]=\"closeButtonAriaLabel()\"\n [testId]=\"closeButtonTestId()\"\n (onClick)=\"dismiss()\" />\n </div>\n </header>\n\n <!--\n Content. This is the element that scrolls, and a scrolling element a\n keyboard cannot reach is content below the fold that a keyboard cannot\n read (#248). The panel's own `tabindex=\"-1\"` above does not cover it: that\n is a focus TARGET, not a tab stop, and it is on the container rather than\n on the element with the overflow.\n\n All three attributes are gated together, and the gate is the point \u2014 an\n unconditional tab stop would land on every panel in the library, including\n the ones whose content fits, where it announces a group and does nothing.\n\n The gate is `contentKeyboardReachable`, which is the measurement OR the\n region's own focus, not the measurement alone. Content that stops\n overflowing while the region is focused would otherwise take the tab stop\n off the focused element and blur a keyboard user out of the open panel.\n Both halves are `tnScrollableRegion`'s, in `../a11y/scrollable-region.ts`,\n which says why in full \u2014 including why it listens for this element's own\n `focus`/`blur` itself rather than leaving each caller to bind them.\n\n `role=\"group\"` rather than the `region` a named `<section>` would imply:\n `region` is a landmark, and a landmark named the same thing in every panel\n is what `landmark-unique` reports the moment two of them are open. A group\n is not summarised, which is what this is.\n -->\n <section\n #content\n class=\"tn-side-panel__content\"\n [attr.tabindex]=\"contentKeyboardReachable() ? '0' : null\"\n [attr.role]=\"contentKeyboardReachable() ? 'group' : null\"\n [attr.aria-label]=\"contentKeyboardReachable() ? contentAriaLabel() : null\">\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);box-shadow:-4px 0 24px #0000004d}.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 #0000;outline:none;transform:translate(100%)}.tn-side-panel__overlay--initialized .tn-side-panel__panel{transition:transform .3s cubic-bezier(.4,0,.2,1),box-shadow .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;margin-left:auto}.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;overflow-wrap:break-word}.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"] }]
|
|
25812
25812
|
}], ctorParameters: () => [], propDecorators: { overlayRef: [{ type: i0.ViewChild, args: ['overlay', { isSignal: true }] }], panelRef: [{ type: i0.ViewChild, args: ['panel', { isSignal: true }] }], contentRef: [{ type: i0.ViewChild, args: ['content', { 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 }] }], closeGuard: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeGuard", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], closeButtonTestId: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeButtonTestId", required: false }] }], closeButtonAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeButtonAriaLabel", required: false }] }], contentAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "contentAriaLabel", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaLabelledby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelledby", required: false }] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], actionContent: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => TnSidePanelActionDirective), { isSignal: true }] }] } });
|
|
25813
25813
|
|
|
25814
25814
|
/**
|