@frame-kit/ui-ng-patterns 0.2.17 → 0.2.19
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.
|
@@ -698,11 +698,11 @@ class SidebarNavComponent {
|
|
|
698
698
|
panel.style.setProperty('--fk-sidebar-nav-flyout-caret-top', `${top}px`);
|
|
699
699
|
}
|
|
700
700
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SidebarNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
701
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SidebarNavComponent, isStandalone: true, selector: "fk-sidebar-nav", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass" } }, queries: [{ propertyName: "itemTpl", first: true, predicate: SidebarNavItemDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "flyoutTpl", first: true, predicate: ["flyoutTpl"], descendants: true, isSignal: true }], ngImport: i0, template: "@for (group of model(); track $index) {\n <div class=\"fk-sidebar-nav__group\">\n @if (group.label) {\n <div class=\"fk-sidebar-nav__group-label\">{{ group.label }}</div>\n }\n <div class=\"fk-sidebar-nav__divider\" aria-hidden=\"true\"></div>\n\n <ul class=\"fk-sidebar-nav__list\">\n @for (item of group.items; track item.id) {\n <li class=\"fk-sidebar-nav__item\">\n @if (isParent(item)) {\n <!-- PARENT \u2014 disclosure row -->\n <button\n #row\n type=\"button\"\n class=\"fk-sidebar-nav__row fk-sidebar-nav__row--parent\"\n [class.fk-sidebar-nav__row--branch]=\"sectionActive(item)\"\n [attr.aria-expanded]=\"\n isCollapsed() ? flyoutItem()?.id === item.id : isOpen(item)\n \"\n [attr.aria-haspopup]=\"isCollapsed() ? 'true' : null\"\n [attr.aria-label]=\"isCollapsed() ? item.label : null\"\n [fkTooltip]=\"item.label\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"onParentClick(item, row)\"\n >\n @if (leadingTemplate(item); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n } @else if (item.icon) {\n <fk-icon\n class=\"fk-sidebar-nav__icon\"\n [name]=\"item.icon\"\n size=\"sm\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{ item.label }}</span>\n <span\n class=\"fk-sidebar-nav__chevron\"\n [class.fk-sidebar-nav__chevron--open]=\"isOpen(item)\"\n aria-hidden=\"true\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 18 18\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M6.75 4.5L11.25 9L6.75 13.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n </button>\n\n @if (!isCollapsed() && isOpen(item)) {\n <ul class=\"fk-sidebar-nav__children\">\n @for (child of item.children; track child.id) {\n @if (child.heading) {\n <li class=\"fk-sidebar-nav__subgroup\">\n <span class=\"fk-sidebar-nav__subgroup-title\">{{\n child.label\n }}</span>\n </li>\n } @else {\n <li>\n <a\n class=\"fk-sidebar-nav__child\"\n [class.fk-sidebar-nav__child--active]=\"\n linkActive(child)\n \"\n [attr.aria-current]=\"linkActive(child) ? 'page' : null\"\n [routerLink]=\"child.routerLink\"\n (click)=\"onLinkClick()\"\n >\n @if (leadingTemplate(child); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: child }\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{\n child.label\n }}</span>\n </a>\n </li>\n }\n }\n </ul>\n }\n } @else {\n <!-- LEAF \u2014 direct link -->\n <a\n class=\"fk-sidebar-nav__row\"\n [class.fk-sidebar-nav__row--active]=\"linkActive(item)\"\n [attr.aria-current]=\"linkActive(item) ? 'page' : null\"\n [routerLink]=\"item.routerLink\"\n [attr.aria-label]=\"isCollapsed() ? item.label : null\"\n [fkTooltip]=\"item.label\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"onLinkClick()\"\n >\n @if (leadingTemplate(item); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n } @else if (item.icon) {\n <fk-icon\n class=\"fk-sidebar-nav__icon\"\n [name]=\"item.icon\"\n size=\"sm\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{ item.label }}</span>\n </a>\n }\n </li>\n }\n </ul>\n </div>\n}\n\n<!-- Flyout panel for a collapsed parent (anchored beside the rail via CDK Overlay) -->\n<ng-template #flyoutTpl let-item>\n <!--\n A labelled group of navigation links \u2014 not an ARIA `menu`. Menu semantics\n promise roving arrow-key focus we don't implement (these are Tab-navigated\n links), so `role=\"group\"` + `aria-label` is the honest, valid structure.\n -->\n <div\n class=\"fk-sidebar-nav__flyout-panel\"\n role=\"group\"\n [attr.aria-label]=\"item.label\"\n >\n <!-- Decorative: the group is already named by aria-label, so the visual\n title/icon would only repeat it to assistive tech. -->\n <div class=\"fk-sidebar-nav__flyout-head\" aria-hidden=\"true\">\n @if (item.icon) {\n <span class=\"fk-sidebar-nav__flyout-icon\">\n <fk-icon [name]=\"item.icon\" size=\"sm\" />\n </span>\n }\n <span class=\"fk-sidebar-nav__flyout-title\">{{ item.label }}</span>\n </div>\n\n <!--\n The items scroll inside their own bounded container, not the panel: the\n panel hosts the caret (::before) which sits outside its left edge, so\n putting overflow on the panel itself would clip it.\n -->\n <div class=\"fk-sidebar-nav__flyout-items\">\n @for (child of item.children; track child.id) {\n @if (child.heading) {\n <span class=\"fk-sidebar-nav__flyout-subgroup\">{{ child.label }}</span>\n } @else {\n <a\n class=\"fk-sidebar-nav__flyout-item\"\n [class.fk-sidebar-nav__flyout-item--active]=\"linkActive(child)\"\n [attr.aria-current]=\"linkActive(child) ? 'page' : null\"\n [routerLink]=\"child.routerLink\"\n (click)=\"onLinkClick()\"\n >\n @if (leadingTemplate(child); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: child }\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{ child.label }}</span>\n </a>\n }\n }\n </div>\n </div>\n</ng-template>\n", styles: [":host{display:block}.fk-sidebar-nav__group{display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-group-inner-gap, var(--fk-rhythm-2, .5rem))}.fk-sidebar-nav__group+.fk-sidebar-nav__group{margin-top:var(--fk-sidebar-nav-group-gap, var(--fk-rhythm-5, 1.25rem))}.fk-sidebar-nav__group-label{padding-inline:var(--fk-sidebar-nav-label-padding-inline, var(--fk-rhythm-3, .75rem));font-family:var(--fk-sidebar-nav-label-font-family, var(--fk-font-family-mono));font-size:var(--fk-sidebar-nav-label-font-size, .625rem);font-weight:var(--fk-sidebar-nav-label-font-weight, var(--fk-font-weight-semibold, 600));letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;color:var(--fk-sidebar-nav-label-color, var(--fk-color-muted, #64748b))}.fk-sidebar-nav__divider{display:none}.fk-sidebar-nav__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-row-stack, var(--fk-rhythm-1, .25rem))}.fk-sidebar-nav__row{box-sizing:border-box;display:flex;align-items:center;margin:0;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));width:100%;padding:var(--fk-sidebar-nav-row-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidebar-nav-row-padding-inline, var(--fk-rhythm-3, .75rem));border:none;border-radius:var(--fk-sidebar-nav-row-radius, var(--fk-radius-md, .625rem));background:var(--fk-sidebar-nav-row-bg, transparent);font-family:var(--fk-sidebar-nav-row-font-family, var(--fk-font-family-base));font-size:var(--fk-sidebar-nav-row-font-size, .875rem);font-weight:var(--fk-sidebar-nav-row-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-sidebar-nav-row-color, var(--fk-color-muted, #36405a));text-align:left;text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .13s ease,color .13s ease}.fk-sidebar-nav__row:hover{background:var(--fk-sidebar-nav-row-bg-hover, var(--fk-color-surface-muted, #f5f6fa));color:var(--fk-sidebar-nav-row-color-hover, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__row:focus-visible{outline:none;box-shadow:var(--fk-sidebar-nav-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(35, 72, 224, .28)))}.fk-sidebar-nav__row--active,.fk-sidebar-nav__row--active:hover{background:var(--fk-sidebar-nav-row-bg-active, var(--fk-color-primary, #2348e0));color:var(--fk-sidebar-nav-row-color-active, #ffffff)}.fk-sidebar-nav__row--active .fk-sidebar-nav__icon{color:var(--fk-sidebar-nav-row-color-active, #ffffff)}.fk-sidebar-nav__row--branch,.fk-sidebar-nav__row--branch:hover{background:var(--fk-sidebar-nav-branch-bg, var(--fk-color-primary-light, #eef2fe));color:var(--fk-sidebar-nav-branch-color, var(--fk-color-primary, #2348e0))}.fk-sidebar-nav__row--branch .fk-sidebar-nav__icon{color:var(--fk-sidebar-nav-branch-color, var(--fk-color-primary, #2348e0))}.fk-sidebar-nav__icon{flex:none;display:inline-flex;color:var(--fk-sidebar-nav-icon-color, var(--fk-color-muted, #8a93a8));transition:color .13s ease}.fk-sidebar-nav__row:hover .fk-sidebar-nav__icon{color:var(--fk-sidebar-nav-icon-color-hover, var(--fk-color-text, #36405a))}.fk-sidebar-nav__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.fk-sidebar-nav__chevron{flex:none;display:inline-flex;align-items:center;justify-content:center;color:var(--fk-sidebar-nav-chevron-color, var(--fk-color-muted, #8a93a8));transition:transform .18s ease}.fk-sidebar-nav__chevron--open{transform:rotate(90deg)}.fk-sidebar-nav__children{position:relative;display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-children-gap, var(--fk-rhythm-2, .5rem));list-style:none;margin:var(--fk-sidebar-nav-children-offset, var(--fk-rhythm-2, .5rem)) 0 0;padding-left:var(--fk-sidebar-nav-children-indent, var(--fk-rhythm-6, 1.5rem))}.fk-sidebar-nav__children:before{content:\"\";position:absolute;top:0;bottom:0;left:var(--fk-sidebar-nav-children-line-offset, var(--fk-rhythm-3, .75rem));width:var(--fk-sidebar-nav-children-line-width, var(--fk-border-width, 1px));background:var(--fk-sidebar-nav-children-line-color, var(--fk-color-border, #e5e8ef))}.fk-sidebar-nav__child{box-sizing:border-box;display:flex;align-items:center;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));width:100%;margin:0;padding:var(--fk-sidebar-nav-child-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidebar-nav-child-padding-inline, var(--fk-rhythm-3, .75rem));border-radius:var(--fk-sidebar-nav-child-radius, var(--fk-radius-md, .625rem));font-size:var(--fk-sidebar-nav-child-font-size, .875rem);font-weight:var(--fk-sidebar-nav-child-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-sidebar-nav-child-color, var(--fk-color-muted, #5c6781));text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .13s ease,color .13s ease}.fk-sidebar-nav__child:hover{background:var(--fk-sidebar-nav-child-bg-hover, var(--fk-color-surface-muted, #f5f6fa));color:var(--fk-sidebar-nav-child-color-hover, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__child:focus-visible{outline:none;box-shadow:var(--fk-sidebar-nav-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(35, 72, 224, .28)))}.fk-sidebar-nav__child--active,.fk-sidebar-nav__child--active:hover{background:var(--fk-sidebar-nav-row-bg-active, var(--fk-color-primary, #2348e0));color:var(--fk-sidebar-nav-row-color-active, #ffffff);font-weight:var(--fk-sidebar-nav-child-font-weight-active, var(--fk-font-weight-semibold, 600))}.fk-sidebar-nav__subgroup{margin:var(--fk-sidebar-nav-subgroup-offset, var(--fk-rhythm-2, .5rem)) 0 0}.fk-sidebar-nav__subgroup-title{display:block;padding-inline:var(--fk-sidebar-nav-child-padding-inline, var(--fk-rhythm-3, .75rem));font-family:var(--fk-sidebar-nav-subgroup-font-family, var(--fk-font-family-mono));font-size:var(--fk-sidebar-nav-subgroup-font-size, .625rem);font-weight:var(--fk-sidebar-nav-subgroup-font-weight, var(--fk-font-weight-semibold, 600));letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;color:var(--fk-sidebar-nav-subgroup-color, var(--fk-color-muted, #8a93a8))}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__group-label{display:none}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__group:not(:first-child) .fk-sidebar-nav__divider{display:block;height:1px;margin:0 var(--fk-sidebar-nav-rail-padding, var(--fk-rhythm-2, .5rem));background:var(--fk-sidebar-nav-children-line-color, var(--fk-color-border, #e5e8ef))}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__row{justify-content:center;padding-inline:var(--fk-sidebar-nav-rail-padding, var(--fk-rhythm-2, .5rem))}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__label,:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__chevron{display:none}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__children{display:none}.fk-sidebar-nav__flyout-panel{position:relative;display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-flyout-gap, var(--fk-rhythm-1, .25rem));min-width:var(--fk-sidebar-nav-flyout-min-width, 13rem);max-width:var(--fk-sidebar-nav-flyout-max-width, 22rem);max-height:var(--fk-sidebar-nav-flyout-max-height, min(28rem, 100dvh - 2rem));padding:var(--fk-sidebar-nav-flyout-padding, var(--fk-rhythm-2, .5rem));background:var(--fk-sidebar-nav-flyout-bg, var(--fk-color-surface, #ffffff));border:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef));border-radius:var(--fk-sidebar-nav-flyout-radius, var(--fk-radius-md, .75rem));box-shadow:var(--fk-sidebar-nav-flyout-shadow, var(--fk-shadow-lg, 0 18px 44px -14px rgba(20, 34, 80, .3)))}.fk-sidebar-nav__flyout-panel:before{content:\"\";position:absolute;left:-.375rem;top:var(--fk-sidebar-nav-flyout-caret-top, 1.375rem);width:.6875rem;height:.6875rem;background:var(--fk-sidebar-nav-flyout-bg, var(--fk-color-surface, #ffffff));border-left:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef));border-bottom:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef));transform:rotate(45deg)}.fk-sidebar-nav__flyout-items{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--fk-sidebar-nav-flyout-gap, var(--fk-rhythm-1, .25rem));min-height:0;overflow-y:auto;overscroll-behavior:contain;padding-inline:var(--fk-focus-ring-width, 3px);margin-inline:calc(var(--fk-focus-ring-width, 3px) * -1)}.fk-sidebar-nav__flyout-head{display:flex;flex-shrink:0;align-items:center;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));padding:.4375rem var(--fk-rhythm-3, .625rem) .5625rem;border-bottom:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef))}.fk-sidebar-nav__flyout-icon{flex:none;display:grid;place-items:center;width:1.5rem;height:1.5rem;border-radius:var(--fk-sidebar-nav-flyout-icon-radius, var(--fk-radius-sm, .5rem));color:var(--fk-sidebar-nav-branch-color, var(--fk-color-primary, #2348e0));background:var(--fk-sidebar-nav-branch-bg, var(--fk-color-primary-light, #eef2fe))}.fk-sidebar-nav__flyout-title{min-width:0;overflow:hidden;font-family:var(--fk-sidebar-nav-flyout-title-font-family, var(--fk-font-family-display, var(--fk-font-family-base)));font-size:var(--fk-sidebar-nav-flyout-title-font-size, .84375rem);font-weight:var(--fk-sidebar-nav-flyout-title-font-weight, var(--fk-font-weight-semibold, 600));white-space:nowrap;text-overflow:ellipsis;color:var(--fk-sidebar-nav-flyout-title-color, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__flyout-subgroup{display:block;flex-shrink:0;padding:var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem) var(--fk-rhythm-1, .25rem);font-family:var(--fk-sidebar-nav-subgroup-font-family, var(--fk-font-family-mono));font-size:var(--fk-sidebar-nav-subgroup-font-size, .625rem);font-weight:var(--fk-sidebar-nav-subgroup-font-weight, var(--fk-font-weight-semibold, 600));letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--fk-sidebar-nav-subgroup-color, var(--fk-color-muted, #8a93a8))}.fk-sidebar-nav__flyout-item{box-sizing:border-box;display:flex;align-items:center;width:100%;margin:0;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));padding:var(--fk-sidebar-nav-row-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidebar-nav-row-padding-inline, var(--fk-rhythm-3, .75rem));border-radius:var(--fk-sidebar-nav-row-radius, var(--fk-radius-md, .5rem));font-size:var(--fk-sidebar-nav-row-font-size, .875rem);font-weight:var(--fk-sidebar-nav-row-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-sidebar-nav-row-color, var(--fk-color-muted, #36405a));text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .12s ease,color .12s ease}.fk-sidebar-nav__flyout-item:hover{background:var(--fk-sidebar-nav-row-bg-hover, var(--fk-color-surface-muted, #f5f6fa));color:var(--fk-sidebar-nav-row-color-hover, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__flyout-item:focus-visible{outline:none;box-shadow:var(--fk-sidebar-nav-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(35, 72, 224, .28)))}.fk-sidebar-nav__flyout-item--active,.fk-sidebar-nav__flyout-item--active:hover{background:var(--fk-sidebar-nav-row-bg-active, var(--fk-color-primary, #2348e0));color:var(--fk-sidebar-nav-row-color-active, #ffffff);font-weight:var(--fk-sidebar-nav-child-font-weight-active, var(--fk-font-weight-semibold, 600))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: IconComponent, selector: "fk-icon", inputs: ["name", "size", "color", "className", "id", "ariaLabel", "ariaHidden"] }, { kind: "directive", type: TooltipDirective, selector: "[fkTooltip]", inputs: ["fkTooltip", "fkTooltipPosition", "fkTooltipOffset", "fkTooltipShowDelay", "fkTooltipHideDelay", "fkTooltipDisabled", "fkTooltipClassName"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
701
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: SidebarNavComponent, isStandalone: true, selector: "fk-sidebar-nav", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, collapsed: { classPropertyName: "collapsed", publicName: "collapsed", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass" } }, queries: [{ propertyName: "itemTpl", first: true, predicate: SidebarNavItemDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "flyoutTpl", first: true, predicate: ["flyoutTpl"], descendants: true, isSignal: true }], ngImport: i0, template: "@for (group of model(); track $index) {\n <div class=\"fk-sidebar-nav__group\">\n @if (group.label) {\n <div class=\"fk-sidebar-nav__group-label\">{{ group.label }}</div>\n }\n <div class=\"fk-sidebar-nav__divider\" aria-hidden=\"true\"></div>\n\n <ul class=\"fk-sidebar-nav__list\">\n @for (item of group.items; track item.id) {\n <li class=\"fk-sidebar-nav__item\">\n @if (isParent(item)) {\n <!-- PARENT \u2014 disclosure row -->\n <button\n #row\n type=\"button\"\n class=\"fk-sidebar-nav__row fk-sidebar-nav__row--parent\"\n [class.fk-sidebar-nav__row--branch]=\"sectionActive(item)\"\n [attr.aria-expanded]=\"\n isCollapsed() ? flyoutItem()?.id === item.id : isOpen(item)\n \"\n [attr.aria-haspopup]=\"isCollapsed() ? 'true' : null\"\n [attr.aria-label]=\"isCollapsed() ? item.label : null\"\n [fkTooltip]=\"item.label\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"onParentClick(item, row)\"\n >\n @if (leadingTemplate(item); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n } @else if (item.icon) {\n <fk-icon\n class=\"fk-sidebar-nav__icon\"\n [name]=\"item.icon\"\n size=\"sm\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{ item.label }}</span>\n <span\n class=\"fk-sidebar-nav__chevron\"\n [class.fk-sidebar-nav__chevron--open]=\"isOpen(item)\"\n aria-hidden=\"true\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 18 18\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M6.75 4.5L11.25 9L6.75 13.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n </button>\n\n @if (!isCollapsed() && isOpen(item)) {\n <ul class=\"fk-sidebar-nav__children\">\n @for (child of item.children; track child.id) {\n @if (child.heading) {\n <li class=\"fk-sidebar-nav__subgroup\">\n <span class=\"fk-sidebar-nav__subgroup-title\">{{\n child.label\n }}</span>\n </li>\n } @else {\n <li>\n <a\n class=\"fk-sidebar-nav__child\"\n [class.fk-sidebar-nav__child--active]=\"\n linkActive(child)\n \"\n [attr.aria-current]=\"linkActive(child) ? 'page' : null\"\n [routerLink]=\"child.routerLink\"\n (click)=\"onLinkClick()\"\n >\n @if (leadingTemplate(child); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: child }\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{\n child.label\n }}</span>\n </a>\n </li>\n }\n }\n </ul>\n }\n } @else {\n <!-- LEAF \u2014 direct link -->\n <a\n class=\"fk-sidebar-nav__row\"\n [class.fk-sidebar-nav__row--active]=\"linkActive(item)\"\n [attr.aria-current]=\"linkActive(item) ? 'page' : null\"\n [routerLink]=\"item.routerLink\"\n [attr.aria-label]=\"isCollapsed() ? item.label : null\"\n [fkTooltip]=\"item.label\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"onLinkClick()\"\n >\n @if (leadingTemplate(item); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n } @else if (item.icon) {\n <fk-icon\n class=\"fk-sidebar-nav__icon\"\n [name]=\"item.icon\"\n size=\"sm\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{ item.label }}</span>\n </a>\n }\n </li>\n }\n </ul>\n </div>\n}\n\n<!-- Flyout panel for a collapsed parent (anchored beside the rail via CDK Overlay) -->\n<ng-template #flyoutTpl let-item>\n <!--\n A labelled group of navigation links \u2014 not an ARIA `menu`. Menu semantics\n promise roving arrow-key focus we don't implement (these are Tab-navigated\n links), so `role=\"group\"` + `aria-label` is the honest, valid structure.\n -->\n <div\n class=\"fk-sidebar-nav__flyout-panel\"\n role=\"group\"\n [attr.aria-label]=\"item.label\"\n >\n <!-- Decorative: the group is already named by aria-label, so the visual\n title/icon would only repeat it to assistive tech. -->\n <div class=\"fk-sidebar-nav__flyout-head\" aria-hidden=\"true\">\n @if (item.icon) {\n <span class=\"fk-sidebar-nav__flyout-icon\">\n <fk-icon [name]=\"item.icon\" size=\"sm\" />\n </span>\n }\n <span class=\"fk-sidebar-nav__flyout-title\">{{ item.label }}</span>\n </div>\n\n <!--\n The items scroll inside their own bounded container, not the panel: the\n panel hosts the caret (::before) which sits outside its left edge, so\n putting overflow on the panel itself would clip it.\n -->\n <div class=\"fk-sidebar-nav__flyout-items\">\n @for (child of item.children; track child.id) {\n @if (child.heading) {\n <span class=\"fk-sidebar-nav__flyout-subgroup\">{{ child.label }}</span>\n } @else {\n <a\n class=\"fk-sidebar-nav__flyout-item\"\n [class.fk-sidebar-nav__flyout-item--active]=\"linkActive(child)\"\n [attr.aria-current]=\"linkActive(child) ? 'page' : null\"\n [routerLink]=\"child.routerLink\"\n (click)=\"onLinkClick()\"\n >\n @if (leadingTemplate(child); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: child }\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{ child.label }}</span>\n </a>\n }\n }\n </div>\n </div>\n</ng-template>\n", styles: [":host{display:block}.fk-sidebar-nav__group{display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-group-inner-gap, var(--fk-rhythm-2, .5rem))}.fk-sidebar-nav__group+.fk-sidebar-nav__group{margin-top:var(--fk-sidebar-nav-group-gap, var(--fk-rhythm-5, 1.25rem))}.fk-sidebar-nav__group-label{padding-inline:var(--fk-sidebar-nav-label-padding-inline, var(--fk-rhythm-3, .75rem));font-family:var(--fk-sidebar-nav-label-font-family, var(--fk-font-family-mono));font-size:var(--fk-sidebar-nav-label-font-size, .625rem);font-weight:var(--fk-sidebar-nav-label-font-weight, var(--fk-font-weight-semibold, 600));letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;color:var(--fk-sidebar-nav-label-color, var(--fk-color-muted, #64748b))}.fk-sidebar-nav__divider{display:none}.fk-sidebar-nav__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-row-stack, var(--fk-rhythm-1, .25rem))}.fk-sidebar-nav__row{box-sizing:border-box;display:flex;align-items:center;margin:0;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));width:100%;padding:var(--fk-sidebar-nav-row-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidebar-nav-row-padding-inline, var(--fk-rhythm-3, .75rem));border:none;border-radius:var(--fk-sidebar-nav-row-radius, var(--fk-radius-md, .625rem));background:var(--fk-sidebar-nav-row-bg, transparent);font-family:var(--fk-sidebar-nav-row-font-family, var(--fk-font-family-base));font-size:var(--fk-sidebar-nav-row-font-size, .875rem);font-weight:var(--fk-sidebar-nav-row-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-sidebar-nav-row-color, var(--fk-color-muted, #36405a));text-align:left;text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .13s ease,color .13s ease}.fk-sidebar-nav__row:hover{background:var(--fk-sidebar-nav-row-bg-hover, var(--fk-color-surface-muted, #f5f6fa));color:var(--fk-sidebar-nav-row-color-hover, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__row:focus-visible{outline:none;box-shadow:var(--fk-sidebar-nav-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(35, 72, 224, .28)))}.fk-sidebar-nav__row--active,.fk-sidebar-nav__row--active:hover{background:var(--fk-sidebar-nav-row-bg-active, var(--fk-color-primary, #2348e0));color:var(--fk-sidebar-nav-row-color-active, #ffffff)}.fk-sidebar-nav__row--branch,.fk-sidebar-nav__row--branch:hover{background:var(--fk-sidebar-nav-branch-bg, var(--fk-color-primary-light, #eef2fe));color:var(--fk-sidebar-nav-branch-color, var(--fk-color-primary, #2348e0))}.fk-sidebar-nav__icon{flex:none;display:inline-flex;color:var(--fk-sidebar-nav-icon-color, var(--fk-color-muted, #8a93a8));transition:color .13s ease}.fk-sidebar-nav__row:hover .fk-sidebar-nav__icon{color:var(--fk-sidebar-nav-icon-color-hover, var(--fk-color-text, #36405a))}.fk-sidebar-nav__row--active .fk-sidebar-nav__icon,.fk-sidebar-nav__row--active:hover .fk-sidebar-nav__icon{color:var(--fk-sidebar-nav-row-color-active, #ffffff)}.fk-sidebar-nav__row--branch .fk-sidebar-nav__icon,.fk-sidebar-nav__row--branch:hover .fk-sidebar-nav__icon{color:var(--fk-sidebar-nav-branch-color, var(--fk-color-primary, #2348e0))}.fk-sidebar-nav__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.fk-sidebar-nav__chevron{flex:none;display:inline-flex;align-items:center;justify-content:center;color:var(--fk-sidebar-nav-chevron-color, var(--fk-color-muted, #8a93a8));transition:transform .18s ease}.fk-sidebar-nav__chevron--open{transform:rotate(90deg)}.fk-sidebar-nav__children{position:relative;display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-children-gap, var(--fk-rhythm-2, .5rem));list-style:none;margin:var(--fk-sidebar-nav-children-offset, var(--fk-rhythm-2, .5rem)) 0 0;padding-left:var(--fk-sidebar-nav-children-indent, var(--fk-rhythm-6, 1.5rem))}.fk-sidebar-nav__children:before{content:\"\";position:absolute;top:0;bottom:0;left:var(--fk-sidebar-nav-children-line-offset, var(--fk-rhythm-3, .75rem));width:var(--fk-sidebar-nav-children-line-width, var(--fk-border-width, 1px));background:var(--fk-sidebar-nav-children-line-color, var(--fk-color-border, #e5e8ef))}.fk-sidebar-nav__child{box-sizing:border-box;display:flex;align-items:center;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));width:100%;margin:0;padding:var(--fk-sidebar-nav-child-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidebar-nav-child-padding-inline, var(--fk-rhythm-3, .75rem));border-radius:var(--fk-sidebar-nav-child-radius, var(--fk-radius-md, .625rem));font-size:var(--fk-sidebar-nav-child-font-size, .875rem);font-weight:var(--fk-sidebar-nav-child-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-sidebar-nav-child-color, var(--fk-color-muted, #5c6781));text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .13s ease,color .13s ease}.fk-sidebar-nav__child:hover{background:var(--fk-sidebar-nav-child-bg-hover, var(--fk-color-surface-muted, #f5f6fa));color:var(--fk-sidebar-nav-child-color-hover, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__child:focus-visible{outline:none;box-shadow:var(--fk-sidebar-nav-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(35, 72, 224, .28)))}.fk-sidebar-nav__child--active,.fk-sidebar-nav__child--active:hover{background:var(--fk-sidebar-nav-row-bg-active, var(--fk-color-primary, #2348e0));color:var(--fk-sidebar-nav-row-color-active, #ffffff);font-weight:var(--fk-sidebar-nav-child-font-weight-active, var(--fk-font-weight-semibold, 600))}.fk-sidebar-nav__subgroup{margin:var(--fk-sidebar-nav-subgroup-offset, var(--fk-rhythm-2, .5rem)) 0 0}.fk-sidebar-nav__subgroup-title{display:block;padding-inline:var(--fk-sidebar-nav-child-padding-inline, var(--fk-rhythm-3, .75rem));font-family:var(--fk-sidebar-nav-subgroup-font-family, var(--fk-font-family-mono));font-size:var(--fk-sidebar-nav-subgroup-font-size, .625rem);font-weight:var(--fk-sidebar-nav-subgroup-font-weight, var(--fk-font-weight-semibold, 600));letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;color:var(--fk-sidebar-nav-subgroup-color, var(--fk-color-muted, #8a93a8))}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__group-label{display:none}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__group:not(:first-child) .fk-sidebar-nav__divider{display:block;height:1px;margin:0 var(--fk-sidebar-nav-rail-padding, var(--fk-rhythm-2, .5rem));background:var(--fk-sidebar-nav-children-line-color, var(--fk-color-border, #e5e8ef))}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__row{justify-content:center;padding-inline:var(--fk-sidebar-nav-rail-padding, var(--fk-rhythm-2, .5rem))}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__label,:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__chevron{display:none}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__children{display:none}.fk-sidebar-nav__flyout-panel{position:relative;display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-flyout-gap, var(--fk-rhythm-1, .25rem));min-width:var(--fk-sidebar-nav-flyout-min-width, 13rem);max-width:var(--fk-sidebar-nav-flyout-max-width, 22rem);max-height:var(--fk-sidebar-nav-flyout-max-height, min(28rem, 100dvh - 2rem));padding:var(--fk-sidebar-nav-flyout-padding, var(--fk-rhythm-2, .5rem));background:var(--fk-sidebar-nav-flyout-bg, var(--fk-color-surface, #ffffff));border:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef));border-radius:var(--fk-sidebar-nav-flyout-radius, var(--fk-radius-md, .75rem));box-shadow:var(--fk-sidebar-nav-flyout-shadow, var(--fk-shadow-lg, 0 18px 44px -14px rgba(20, 34, 80, .3)))}.fk-sidebar-nav__flyout-panel:before{content:\"\";position:absolute;left:-.375rem;top:var(--fk-sidebar-nav-flyout-caret-top, 1.375rem);width:.6875rem;height:.6875rem;background:var(--fk-sidebar-nav-flyout-bg, var(--fk-color-surface, #ffffff));border-left:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef));border-bottom:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef));transform:rotate(45deg)}.fk-sidebar-nav__flyout-items{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--fk-sidebar-nav-flyout-gap, var(--fk-rhythm-1, .25rem));min-height:0;overflow-y:auto;overscroll-behavior:contain;padding-inline:var(--fk-focus-ring-width, 3px);margin-inline:calc(var(--fk-focus-ring-width, 3px) * -1)}.fk-sidebar-nav__flyout-head{display:flex;flex-shrink:0;align-items:center;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));padding:.4375rem var(--fk-rhythm-3, .625rem) .5625rem;border-bottom:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef))}.fk-sidebar-nav__flyout-icon{flex:none;display:grid;place-items:center;width:1.5rem;height:1.5rem;border-radius:var(--fk-sidebar-nav-flyout-icon-radius, var(--fk-radius-sm, .5rem));color:var(--fk-sidebar-nav-branch-color, var(--fk-color-primary, #2348e0));background:var(--fk-sidebar-nav-branch-bg, var(--fk-color-primary-light, #eef2fe))}.fk-sidebar-nav__flyout-title{min-width:0;overflow:hidden;font-family:var(--fk-sidebar-nav-flyout-title-font-family, var(--fk-font-family-display, var(--fk-font-family-base)));font-size:var(--fk-sidebar-nav-flyout-title-font-size, .84375rem);font-weight:var(--fk-sidebar-nav-flyout-title-font-weight, var(--fk-font-weight-semibold, 600));white-space:nowrap;text-overflow:ellipsis;color:var(--fk-sidebar-nav-flyout-title-color, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__flyout-subgroup{display:block;flex-shrink:0;padding:var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem) var(--fk-rhythm-1, .25rem);font-family:var(--fk-sidebar-nav-subgroup-font-family, var(--fk-font-family-mono));font-size:var(--fk-sidebar-nav-subgroup-font-size, .625rem);font-weight:var(--fk-sidebar-nav-subgroup-font-weight, var(--fk-font-weight-semibold, 600));letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--fk-sidebar-nav-subgroup-color, var(--fk-color-muted, #8a93a8))}.fk-sidebar-nav__flyout-item{box-sizing:border-box;display:flex;align-items:center;width:100%;margin:0;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));padding:var(--fk-sidebar-nav-row-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidebar-nav-row-padding-inline, var(--fk-rhythm-3, .75rem));border-radius:var(--fk-sidebar-nav-row-radius, var(--fk-radius-md, .5rem));font-size:var(--fk-sidebar-nav-row-font-size, .875rem);font-weight:var(--fk-sidebar-nav-row-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-sidebar-nav-row-color, var(--fk-color-muted, #36405a));text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .12s ease,color .12s ease}.fk-sidebar-nav__flyout-item:hover{background:var(--fk-sidebar-nav-row-bg-hover, var(--fk-color-surface-muted, #f5f6fa));color:var(--fk-sidebar-nav-row-color-hover, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__flyout-item:focus-visible{outline:none;box-shadow:var(--fk-sidebar-nav-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(35, 72, 224, .28)))}.fk-sidebar-nav__flyout-item--active,.fk-sidebar-nav__flyout-item--active:hover{background:var(--fk-sidebar-nav-row-bg-active, var(--fk-color-primary, #2348e0));color:var(--fk-sidebar-nav-row-color-active, #ffffff);font-weight:var(--fk-sidebar-nav-child-font-weight-active, var(--fk-font-weight-semibold, 600))}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: IconComponent, selector: "fk-icon", inputs: ["name", "size", "color", "className", "id", "ariaLabel", "ariaHidden"] }, { kind: "directive", type: TooltipDirective, selector: "[fkTooltip]", inputs: ["fkTooltip", "fkTooltipPosition", "fkTooltipOffset", "fkTooltipShowDelay", "fkTooltipHideDelay", "fkTooltipDisabled", "fkTooltipClassName"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
702
702
|
}
|
|
703
703
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: SidebarNavComponent, decorators: [{
|
|
704
704
|
type: Component,
|
|
705
|
-
args: [{ selector: 'fk-sidebar-nav', standalone: true, imports: [RouterLink, IconComponent, TooltipDirective, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "@for (group of model(); track $index) {\n <div class=\"fk-sidebar-nav__group\">\n @if (group.label) {\n <div class=\"fk-sidebar-nav__group-label\">{{ group.label }}</div>\n }\n <div class=\"fk-sidebar-nav__divider\" aria-hidden=\"true\"></div>\n\n <ul class=\"fk-sidebar-nav__list\">\n @for (item of group.items; track item.id) {\n <li class=\"fk-sidebar-nav__item\">\n @if (isParent(item)) {\n <!-- PARENT \u2014 disclosure row -->\n <button\n #row\n type=\"button\"\n class=\"fk-sidebar-nav__row fk-sidebar-nav__row--parent\"\n [class.fk-sidebar-nav__row--branch]=\"sectionActive(item)\"\n [attr.aria-expanded]=\"\n isCollapsed() ? flyoutItem()?.id === item.id : isOpen(item)\n \"\n [attr.aria-haspopup]=\"isCollapsed() ? 'true' : null\"\n [attr.aria-label]=\"isCollapsed() ? item.label : null\"\n [fkTooltip]=\"item.label\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"onParentClick(item, row)\"\n >\n @if (leadingTemplate(item); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n } @else if (item.icon) {\n <fk-icon\n class=\"fk-sidebar-nav__icon\"\n [name]=\"item.icon\"\n size=\"sm\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{ item.label }}</span>\n <span\n class=\"fk-sidebar-nav__chevron\"\n [class.fk-sidebar-nav__chevron--open]=\"isOpen(item)\"\n aria-hidden=\"true\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 18 18\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M6.75 4.5L11.25 9L6.75 13.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n </button>\n\n @if (!isCollapsed() && isOpen(item)) {\n <ul class=\"fk-sidebar-nav__children\">\n @for (child of item.children; track child.id) {\n @if (child.heading) {\n <li class=\"fk-sidebar-nav__subgroup\">\n <span class=\"fk-sidebar-nav__subgroup-title\">{{\n child.label\n }}</span>\n </li>\n } @else {\n <li>\n <a\n class=\"fk-sidebar-nav__child\"\n [class.fk-sidebar-nav__child--active]=\"\n linkActive(child)\n \"\n [attr.aria-current]=\"linkActive(child) ? 'page' : null\"\n [routerLink]=\"child.routerLink\"\n (click)=\"onLinkClick()\"\n >\n @if (leadingTemplate(child); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: child }\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{\n child.label\n }}</span>\n </a>\n </li>\n }\n }\n </ul>\n }\n } @else {\n <!-- LEAF \u2014 direct link -->\n <a\n class=\"fk-sidebar-nav__row\"\n [class.fk-sidebar-nav__row--active]=\"linkActive(item)\"\n [attr.aria-current]=\"linkActive(item) ? 'page' : null\"\n [routerLink]=\"item.routerLink\"\n [attr.aria-label]=\"isCollapsed() ? item.label : null\"\n [fkTooltip]=\"item.label\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"onLinkClick()\"\n >\n @if (leadingTemplate(item); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n } @else if (item.icon) {\n <fk-icon\n class=\"fk-sidebar-nav__icon\"\n [name]=\"item.icon\"\n size=\"sm\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{ item.label }}</span>\n </a>\n }\n </li>\n }\n </ul>\n </div>\n}\n\n<!-- Flyout panel for a collapsed parent (anchored beside the rail via CDK Overlay) -->\n<ng-template #flyoutTpl let-item>\n <!--\n A labelled group of navigation links \u2014 not an ARIA `menu`. Menu semantics\n promise roving arrow-key focus we don't implement (these are Tab-navigated\n links), so `role=\"group\"` + `aria-label` is the honest, valid structure.\n -->\n <div\n class=\"fk-sidebar-nav__flyout-panel\"\n role=\"group\"\n [attr.aria-label]=\"item.label\"\n >\n <!-- Decorative: the group is already named by aria-label, so the visual\n title/icon would only repeat it to assistive tech. -->\n <div class=\"fk-sidebar-nav__flyout-head\" aria-hidden=\"true\">\n @if (item.icon) {\n <span class=\"fk-sidebar-nav__flyout-icon\">\n <fk-icon [name]=\"item.icon\" size=\"sm\" />\n </span>\n }\n <span class=\"fk-sidebar-nav__flyout-title\">{{ item.label }}</span>\n </div>\n\n <!--\n The items scroll inside their own bounded container, not the panel: the\n panel hosts the caret (::before) which sits outside its left edge, so\n putting overflow on the panel itself would clip it.\n -->\n <div class=\"fk-sidebar-nav__flyout-items\">\n @for (child of item.children; track child.id) {\n @if (child.heading) {\n <span class=\"fk-sidebar-nav__flyout-subgroup\">{{ child.label }}</span>\n } @else {\n <a\n class=\"fk-sidebar-nav__flyout-item\"\n [class.fk-sidebar-nav__flyout-item--active]=\"linkActive(child)\"\n [attr.aria-current]=\"linkActive(child) ? 'page' : null\"\n [routerLink]=\"child.routerLink\"\n (click)=\"onLinkClick()\"\n >\n @if (leadingTemplate(child); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: child }\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{ child.label }}</span>\n </a>\n }\n }\n </div>\n </div>\n</ng-template>\n", styles: [":host{display:block}.fk-sidebar-nav__group{display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-group-inner-gap, var(--fk-rhythm-2, .5rem))}.fk-sidebar-nav__group+.fk-sidebar-nav__group{margin-top:var(--fk-sidebar-nav-group-gap, var(--fk-rhythm-5, 1.25rem))}.fk-sidebar-nav__group-label{padding-inline:var(--fk-sidebar-nav-label-padding-inline, var(--fk-rhythm-3, .75rem));font-family:var(--fk-sidebar-nav-label-font-family, var(--fk-font-family-mono));font-size:var(--fk-sidebar-nav-label-font-size, .625rem);font-weight:var(--fk-sidebar-nav-label-font-weight, var(--fk-font-weight-semibold, 600));letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;color:var(--fk-sidebar-nav-label-color, var(--fk-color-muted, #64748b))}.fk-sidebar-nav__divider{display:none}.fk-sidebar-nav__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-row-stack, var(--fk-rhythm-1, .25rem))}.fk-sidebar-nav__row{box-sizing:border-box;display:flex;align-items:center;margin:0;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));width:100%;padding:var(--fk-sidebar-nav-row-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidebar-nav-row-padding-inline, var(--fk-rhythm-3, .75rem));border:none;border-radius:var(--fk-sidebar-nav-row-radius, var(--fk-radius-md, .625rem));background:var(--fk-sidebar-nav-row-bg, transparent);font-family:var(--fk-sidebar-nav-row-font-family, var(--fk-font-family-base));font-size:var(--fk-sidebar-nav-row-font-size, .875rem);font-weight:var(--fk-sidebar-nav-row-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-sidebar-nav-row-color, var(--fk-color-muted, #36405a));text-align:left;text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .13s ease,color .13s ease}.fk-sidebar-nav__row:hover{background:var(--fk-sidebar-nav-row-bg-hover, var(--fk-color-surface-muted, #f5f6fa));color:var(--fk-sidebar-nav-row-color-hover, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__row:focus-visible{outline:none;box-shadow:var(--fk-sidebar-nav-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(35, 72, 224, .28)))}.fk-sidebar-nav__row--active,.fk-sidebar-nav__row--active:hover{background:var(--fk-sidebar-nav-row-bg-active, var(--fk-color-primary, #2348e0));color:var(--fk-sidebar-nav-row-color-active, #ffffff)}.fk-sidebar-nav__row--active .fk-sidebar-nav__icon{color:var(--fk-sidebar-nav-row-color-active, #ffffff)}.fk-sidebar-nav__row--branch,.fk-sidebar-nav__row--branch:hover{background:var(--fk-sidebar-nav-branch-bg, var(--fk-color-primary-light, #eef2fe));color:var(--fk-sidebar-nav-branch-color, var(--fk-color-primary, #2348e0))}.fk-sidebar-nav__row--branch .fk-sidebar-nav__icon{color:var(--fk-sidebar-nav-branch-color, var(--fk-color-primary, #2348e0))}.fk-sidebar-nav__icon{flex:none;display:inline-flex;color:var(--fk-sidebar-nav-icon-color, var(--fk-color-muted, #8a93a8));transition:color .13s ease}.fk-sidebar-nav__row:hover .fk-sidebar-nav__icon{color:var(--fk-sidebar-nav-icon-color-hover, var(--fk-color-text, #36405a))}.fk-sidebar-nav__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.fk-sidebar-nav__chevron{flex:none;display:inline-flex;align-items:center;justify-content:center;color:var(--fk-sidebar-nav-chevron-color, var(--fk-color-muted, #8a93a8));transition:transform .18s ease}.fk-sidebar-nav__chevron--open{transform:rotate(90deg)}.fk-sidebar-nav__children{position:relative;display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-children-gap, var(--fk-rhythm-2, .5rem));list-style:none;margin:var(--fk-sidebar-nav-children-offset, var(--fk-rhythm-2, .5rem)) 0 0;padding-left:var(--fk-sidebar-nav-children-indent, var(--fk-rhythm-6, 1.5rem))}.fk-sidebar-nav__children:before{content:\"\";position:absolute;top:0;bottom:0;left:var(--fk-sidebar-nav-children-line-offset, var(--fk-rhythm-3, .75rem));width:var(--fk-sidebar-nav-children-line-width, var(--fk-border-width, 1px));background:var(--fk-sidebar-nav-children-line-color, var(--fk-color-border, #e5e8ef))}.fk-sidebar-nav__child{box-sizing:border-box;display:flex;align-items:center;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));width:100%;margin:0;padding:var(--fk-sidebar-nav-child-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidebar-nav-child-padding-inline, var(--fk-rhythm-3, .75rem));border-radius:var(--fk-sidebar-nav-child-radius, var(--fk-radius-md, .625rem));font-size:var(--fk-sidebar-nav-child-font-size, .875rem);font-weight:var(--fk-sidebar-nav-child-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-sidebar-nav-child-color, var(--fk-color-muted, #5c6781));text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .13s ease,color .13s ease}.fk-sidebar-nav__child:hover{background:var(--fk-sidebar-nav-child-bg-hover, var(--fk-color-surface-muted, #f5f6fa));color:var(--fk-sidebar-nav-child-color-hover, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__child:focus-visible{outline:none;box-shadow:var(--fk-sidebar-nav-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(35, 72, 224, .28)))}.fk-sidebar-nav__child--active,.fk-sidebar-nav__child--active:hover{background:var(--fk-sidebar-nav-row-bg-active, var(--fk-color-primary, #2348e0));color:var(--fk-sidebar-nav-row-color-active, #ffffff);font-weight:var(--fk-sidebar-nav-child-font-weight-active, var(--fk-font-weight-semibold, 600))}.fk-sidebar-nav__subgroup{margin:var(--fk-sidebar-nav-subgroup-offset, var(--fk-rhythm-2, .5rem)) 0 0}.fk-sidebar-nav__subgroup-title{display:block;padding-inline:var(--fk-sidebar-nav-child-padding-inline, var(--fk-rhythm-3, .75rem));font-family:var(--fk-sidebar-nav-subgroup-font-family, var(--fk-font-family-mono));font-size:var(--fk-sidebar-nav-subgroup-font-size, .625rem);font-weight:var(--fk-sidebar-nav-subgroup-font-weight, var(--fk-font-weight-semibold, 600));letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;color:var(--fk-sidebar-nav-subgroup-color, var(--fk-color-muted, #8a93a8))}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__group-label{display:none}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__group:not(:first-child) .fk-sidebar-nav__divider{display:block;height:1px;margin:0 var(--fk-sidebar-nav-rail-padding, var(--fk-rhythm-2, .5rem));background:var(--fk-sidebar-nav-children-line-color, var(--fk-color-border, #e5e8ef))}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__row{justify-content:center;padding-inline:var(--fk-sidebar-nav-rail-padding, var(--fk-rhythm-2, .5rem))}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__label,:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__chevron{display:none}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__children{display:none}.fk-sidebar-nav__flyout-panel{position:relative;display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-flyout-gap, var(--fk-rhythm-1, .25rem));min-width:var(--fk-sidebar-nav-flyout-min-width, 13rem);max-width:var(--fk-sidebar-nav-flyout-max-width, 22rem);max-height:var(--fk-sidebar-nav-flyout-max-height, min(28rem, 100dvh - 2rem));padding:var(--fk-sidebar-nav-flyout-padding, var(--fk-rhythm-2, .5rem));background:var(--fk-sidebar-nav-flyout-bg, var(--fk-color-surface, #ffffff));border:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef));border-radius:var(--fk-sidebar-nav-flyout-radius, var(--fk-radius-md, .75rem));box-shadow:var(--fk-sidebar-nav-flyout-shadow, var(--fk-shadow-lg, 0 18px 44px -14px rgba(20, 34, 80, .3)))}.fk-sidebar-nav__flyout-panel:before{content:\"\";position:absolute;left:-.375rem;top:var(--fk-sidebar-nav-flyout-caret-top, 1.375rem);width:.6875rem;height:.6875rem;background:var(--fk-sidebar-nav-flyout-bg, var(--fk-color-surface, #ffffff));border-left:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef));border-bottom:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef));transform:rotate(45deg)}.fk-sidebar-nav__flyout-items{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--fk-sidebar-nav-flyout-gap, var(--fk-rhythm-1, .25rem));min-height:0;overflow-y:auto;overscroll-behavior:contain;padding-inline:var(--fk-focus-ring-width, 3px);margin-inline:calc(var(--fk-focus-ring-width, 3px) * -1)}.fk-sidebar-nav__flyout-head{display:flex;flex-shrink:0;align-items:center;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));padding:.4375rem var(--fk-rhythm-3, .625rem) .5625rem;border-bottom:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef))}.fk-sidebar-nav__flyout-icon{flex:none;display:grid;place-items:center;width:1.5rem;height:1.5rem;border-radius:var(--fk-sidebar-nav-flyout-icon-radius, var(--fk-radius-sm, .5rem));color:var(--fk-sidebar-nav-branch-color, var(--fk-color-primary, #2348e0));background:var(--fk-sidebar-nav-branch-bg, var(--fk-color-primary-light, #eef2fe))}.fk-sidebar-nav__flyout-title{min-width:0;overflow:hidden;font-family:var(--fk-sidebar-nav-flyout-title-font-family, var(--fk-font-family-display, var(--fk-font-family-base)));font-size:var(--fk-sidebar-nav-flyout-title-font-size, .84375rem);font-weight:var(--fk-sidebar-nav-flyout-title-font-weight, var(--fk-font-weight-semibold, 600));white-space:nowrap;text-overflow:ellipsis;color:var(--fk-sidebar-nav-flyout-title-color, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__flyout-subgroup{display:block;flex-shrink:0;padding:var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem) var(--fk-rhythm-1, .25rem);font-family:var(--fk-sidebar-nav-subgroup-font-family, var(--fk-font-family-mono));font-size:var(--fk-sidebar-nav-subgroup-font-size, .625rem);font-weight:var(--fk-sidebar-nav-subgroup-font-weight, var(--fk-font-weight-semibold, 600));letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--fk-sidebar-nav-subgroup-color, var(--fk-color-muted, #8a93a8))}.fk-sidebar-nav__flyout-item{box-sizing:border-box;display:flex;align-items:center;width:100%;margin:0;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));padding:var(--fk-sidebar-nav-row-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidebar-nav-row-padding-inline, var(--fk-rhythm-3, .75rem));border-radius:var(--fk-sidebar-nav-row-radius, var(--fk-radius-md, .5rem));font-size:var(--fk-sidebar-nav-row-font-size, .875rem);font-weight:var(--fk-sidebar-nav-row-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-sidebar-nav-row-color, var(--fk-color-muted, #36405a));text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .12s ease,color .12s ease}.fk-sidebar-nav__flyout-item:hover{background:var(--fk-sidebar-nav-row-bg-hover, var(--fk-color-surface-muted, #f5f6fa));color:var(--fk-sidebar-nav-row-color-hover, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__flyout-item:focus-visible{outline:none;box-shadow:var(--fk-sidebar-nav-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(35, 72, 224, .28)))}.fk-sidebar-nav__flyout-item--active,.fk-sidebar-nav__flyout-item--active:hover{background:var(--fk-sidebar-nav-row-bg-active, var(--fk-color-primary, #2348e0));color:var(--fk-sidebar-nav-row-color-active, #ffffff);font-weight:var(--fk-sidebar-nav-child-font-weight-active, var(--fk-font-weight-semibold, 600))}\n"] }]
|
|
705
|
+
args: [{ selector: 'fk-sidebar-nav', standalone: true, imports: [RouterLink, IconComponent, TooltipDirective, NgTemplateOutlet], changeDetection: ChangeDetectionStrategy.OnPush, template: "@for (group of model(); track $index) {\n <div class=\"fk-sidebar-nav__group\">\n @if (group.label) {\n <div class=\"fk-sidebar-nav__group-label\">{{ group.label }}</div>\n }\n <div class=\"fk-sidebar-nav__divider\" aria-hidden=\"true\"></div>\n\n <ul class=\"fk-sidebar-nav__list\">\n @for (item of group.items; track item.id) {\n <li class=\"fk-sidebar-nav__item\">\n @if (isParent(item)) {\n <!-- PARENT \u2014 disclosure row -->\n <button\n #row\n type=\"button\"\n class=\"fk-sidebar-nav__row fk-sidebar-nav__row--parent\"\n [class.fk-sidebar-nav__row--branch]=\"sectionActive(item)\"\n [attr.aria-expanded]=\"\n isCollapsed() ? flyoutItem()?.id === item.id : isOpen(item)\n \"\n [attr.aria-haspopup]=\"isCollapsed() ? 'true' : null\"\n [attr.aria-label]=\"isCollapsed() ? item.label : null\"\n [fkTooltip]=\"item.label\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"onParentClick(item, row)\"\n >\n @if (leadingTemplate(item); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n } @else if (item.icon) {\n <fk-icon\n class=\"fk-sidebar-nav__icon\"\n [name]=\"item.icon\"\n size=\"sm\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{ item.label }}</span>\n <span\n class=\"fk-sidebar-nav__chevron\"\n [class.fk-sidebar-nav__chevron--open]=\"isOpen(item)\"\n aria-hidden=\"true\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 18 18\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M6.75 4.5L11.25 9L6.75 13.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n fill=\"none\"\n />\n </svg>\n </span>\n </button>\n\n @if (!isCollapsed() && isOpen(item)) {\n <ul class=\"fk-sidebar-nav__children\">\n @for (child of item.children; track child.id) {\n @if (child.heading) {\n <li class=\"fk-sidebar-nav__subgroup\">\n <span class=\"fk-sidebar-nav__subgroup-title\">{{\n child.label\n }}</span>\n </li>\n } @else {\n <li>\n <a\n class=\"fk-sidebar-nav__child\"\n [class.fk-sidebar-nav__child--active]=\"\n linkActive(child)\n \"\n [attr.aria-current]=\"linkActive(child) ? 'page' : null\"\n [routerLink]=\"child.routerLink\"\n (click)=\"onLinkClick()\"\n >\n @if (leadingTemplate(child); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: child }\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{\n child.label\n }}</span>\n </a>\n </li>\n }\n }\n </ul>\n }\n } @else {\n <!-- LEAF \u2014 direct link -->\n <a\n class=\"fk-sidebar-nav__row\"\n [class.fk-sidebar-nav__row--active]=\"linkActive(item)\"\n [attr.aria-current]=\"linkActive(item) ? 'page' : null\"\n [routerLink]=\"item.routerLink\"\n [attr.aria-label]=\"isCollapsed() ? item.label : null\"\n [fkTooltip]=\"item.label\"\n [fkTooltipDisabled]=\"!isCollapsed()\"\n fkTooltipPosition=\"right\"\n (click)=\"onLinkClick()\"\n >\n @if (leadingTemplate(item); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: item }\"\n />\n } @else if (item.icon) {\n <fk-icon\n class=\"fk-sidebar-nav__icon\"\n [name]=\"item.icon\"\n size=\"sm\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{ item.label }}</span>\n </a>\n }\n </li>\n }\n </ul>\n </div>\n}\n\n<!-- Flyout panel for a collapsed parent (anchored beside the rail via CDK Overlay) -->\n<ng-template #flyoutTpl let-item>\n <!--\n A labelled group of navigation links \u2014 not an ARIA `menu`. Menu semantics\n promise roving arrow-key focus we don't implement (these are Tab-navigated\n links), so `role=\"group\"` + `aria-label` is the honest, valid structure.\n -->\n <div\n class=\"fk-sidebar-nav__flyout-panel\"\n role=\"group\"\n [attr.aria-label]=\"item.label\"\n >\n <!-- Decorative: the group is already named by aria-label, so the visual\n title/icon would only repeat it to assistive tech. -->\n <div class=\"fk-sidebar-nav__flyout-head\" aria-hidden=\"true\">\n @if (item.icon) {\n <span class=\"fk-sidebar-nav__flyout-icon\">\n <fk-icon [name]=\"item.icon\" size=\"sm\" />\n </span>\n }\n <span class=\"fk-sidebar-nav__flyout-title\">{{ item.label }}</span>\n </div>\n\n <!--\n The items scroll inside their own bounded container, not the panel: the\n panel hosts the caret (::before) which sits outside its left edge, so\n putting overflow on the panel itself would clip it.\n -->\n <div class=\"fk-sidebar-nav__flyout-items\">\n @for (child of item.children; track child.id) {\n @if (child.heading) {\n <span class=\"fk-sidebar-nav__flyout-subgroup\">{{ child.label }}</span>\n } @else {\n <a\n class=\"fk-sidebar-nav__flyout-item\"\n [class.fk-sidebar-nav__flyout-item--active]=\"linkActive(child)\"\n [attr.aria-current]=\"linkActive(child) ? 'page' : null\"\n [routerLink]=\"child.routerLink\"\n (click)=\"onLinkClick()\"\n >\n @if (leadingTemplate(child); as tpl) {\n <ng-container\n [ngTemplateOutlet]=\"tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: child }\"\n />\n }\n <span class=\"fk-sidebar-nav__label\">{{ child.label }}</span>\n </a>\n }\n }\n </div>\n </div>\n</ng-template>\n", styles: [":host{display:block}.fk-sidebar-nav__group{display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-group-inner-gap, var(--fk-rhythm-2, .5rem))}.fk-sidebar-nav__group+.fk-sidebar-nav__group{margin-top:var(--fk-sidebar-nav-group-gap, var(--fk-rhythm-5, 1.25rem))}.fk-sidebar-nav__group-label{padding-inline:var(--fk-sidebar-nav-label-padding-inline, var(--fk-rhythm-3, .75rem));font-family:var(--fk-sidebar-nav-label-font-family, var(--fk-font-family-mono));font-size:var(--fk-sidebar-nav-label-font-size, .625rem);font-weight:var(--fk-sidebar-nav-label-font-weight, var(--fk-font-weight-semibold, 600));letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;color:var(--fk-sidebar-nav-label-color, var(--fk-color-muted, #64748b))}.fk-sidebar-nav__divider{display:none}.fk-sidebar-nav__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-row-stack, var(--fk-rhythm-1, .25rem))}.fk-sidebar-nav__row{box-sizing:border-box;display:flex;align-items:center;margin:0;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));width:100%;padding:var(--fk-sidebar-nav-row-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidebar-nav-row-padding-inline, var(--fk-rhythm-3, .75rem));border:none;border-radius:var(--fk-sidebar-nav-row-radius, var(--fk-radius-md, .625rem));background:var(--fk-sidebar-nav-row-bg, transparent);font-family:var(--fk-sidebar-nav-row-font-family, var(--fk-font-family-base));font-size:var(--fk-sidebar-nav-row-font-size, .875rem);font-weight:var(--fk-sidebar-nav-row-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-sidebar-nav-row-color, var(--fk-color-muted, #36405a));text-align:left;text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .13s ease,color .13s ease}.fk-sidebar-nav__row:hover{background:var(--fk-sidebar-nav-row-bg-hover, var(--fk-color-surface-muted, #f5f6fa));color:var(--fk-sidebar-nav-row-color-hover, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__row:focus-visible{outline:none;box-shadow:var(--fk-sidebar-nav-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(35, 72, 224, .28)))}.fk-sidebar-nav__row--active,.fk-sidebar-nav__row--active:hover{background:var(--fk-sidebar-nav-row-bg-active, var(--fk-color-primary, #2348e0));color:var(--fk-sidebar-nav-row-color-active, #ffffff)}.fk-sidebar-nav__row--branch,.fk-sidebar-nav__row--branch:hover{background:var(--fk-sidebar-nav-branch-bg, var(--fk-color-primary-light, #eef2fe));color:var(--fk-sidebar-nav-branch-color, var(--fk-color-primary, #2348e0))}.fk-sidebar-nav__icon{flex:none;display:inline-flex;color:var(--fk-sidebar-nav-icon-color, var(--fk-color-muted, #8a93a8));transition:color .13s ease}.fk-sidebar-nav__row:hover .fk-sidebar-nav__icon{color:var(--fk-sidebar-nav-icon-color-hover, var(--fk-color-text, #36405a))}.fk-sidebar-nav__row--active .fk-sidebar-nav__icon,.fk-sidebar-nav__row--active:hover .fk-sidebar-nav__icon{color:var(--fk-sidebar-nav-row-color-active, #ffffff)}.fk-sidebar-nav__row--branch .fk-sidebar-nav__icon,.fk-sidebar-nav__row--branch:hover .fk-sidebar-nav__icon{color:var(--fk-sidebar-nav-branch-color, var(--fk-color-primary, #2348e0))}.fk-sidebar-nav__label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.fk-sidebar-nav__chevron{flex:none;display:inline-flex;align-items:center;justify-content:center;color:var(--fk-sidebar-nav-chevron-color, var(--fk-color-muted, #8a93a8));transition:transform .18s ease}.fk-sidebar-nav__chevron--open{transform:rotate(90deg)}.fk-sidebar-nav__children{position:relative;display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-children-gap, var(--fk-rhythm-2, .5rem));list-style:none;margin:var(--fk-sidebar-nav-children-offset, var(--fk-rhythm-2, .5rem)) 0 0;padding-left:var(--fk-sidebar-nav-children-indent, var(--fk-rhythm-6, 1.5rem))}.fk-sidebar-nav__children:before{content:\"\";position:absolute;top:0;bottom:0;left:var(--fk-sidebar-nav-children-line-offset, var(--fk-rhythm-3, .75rem));width:var(--fk-sidebar-nav-children-line-width, var(--fk-border-width, 1px));background:var(--fk-sidebar-nav-children-line-color, var(--fk-color-border, #e5e8ef))}.fk-sidebar-nav__child{box-sizing:border-box;display:flex;align-items:center;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));width:100%;margin:0;padding:var(--fk-sidebar-nav-child-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidebar-nav-child-padding-inline, var(--fk-rhythm-3, .75rem));border-radius:var(--fk-sidebar-nav-child-radius, var(--fk-radius-md, .625rem));font-size:var(--fk-sidebar-nav-child-font-size, .875rem);font-weight:var(--fk-sidebar-nav-child-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-sidebar-nav-child-color, var(--fk-color-muted, #5c6781));text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .13s ease,color .13s ease}.fk-sidebar-nav__child:hover{background:var(--fk-sidebar-nav-child-bg-hover, var(--fk-color-surface-muted, #f5f6fa));color:var(--fk-sidebar-nav-child-color-hover, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__child:focus-visible{outline:none;box-shadow:var(--fk-sidebar-nav-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(35, 72, 224, .28)))}.fk-sidebar-nav__child--active,.fk-sidebar-nav__child--active:hover{background:var(--fk-sidebar-nav-row-bg-active, var(--fk-color-primary, #2348e0));color:var(--fk-sidebar-nav-row-color-active, #ffffff);font-weight:var(--fk-sidebar-nav-child-font-weight-active, var(--fk-font-weight-semibold, 600))}.fk-sidebar-nav__subgroup{margin:var(--fk-sidebar-nav-subgroup-offset, var(--fk-rhythm-2, .5rem)) 0 0}.fk-sidebar-nav__subgroup-title{display:block;padding-inline:var(--fk-sidebar-nav-child-padding-inline, var(--fk-rhythm-3, .75rem));font-family:var(--fk-sidebar-nav-subgroup-font-family, var(--fk-font-family-mono));font-size:var(--fk-sidebar-nav-subgroup-font-size, .625rem);font-weight:var(--fk-sidebar-nav-subgroup-font-weight, var(--fk-font-weight-semibold, 600));letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;color:var(--fk-sidebar-nav-subgroup-color, var(--fk-color-muted, #8a93a8))}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__group-label{display:none}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__group:not(:first-child) .fk-sidebar-nav__divider{display:block;height:1px;margin:0 var(--fk-sidebar-nav-rail-padding, var(--fk-rhythm-2, .5rem));background:var(--fk-sidebar-nav-children-line-color, var(--fk-color-border, #e5e8ef))}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__row{justify-content:center;padding-inline:var(--fk-sidebar-nav-rail-padding, var(--fk-rhythm-2, .5rem))}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__label,:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__chevron{display:none}:host(.fk-sidebar-nav--collapsed) .fk-sidebar-nav__children{display:none}.fk-sidebar-nav__flyout-panel{position:relative;display:flex;flex-direction:column;gap:var(--fk-sidebar-nav-flyout-gap, var(--fk-rhythm-1, .25rem));min-width:var(--fk-sidebar-nav-flyout-min-width, 13rem);max-width:var(--fk-sidebar-nav-flyout-max-width, 22rem);max-height:var(--fk-sidebar-nav-flyout-max-height, min(28rem, 100dvh - 2rem));padding:var(--fk-sidebar-nav-flyout-padding, var(--fk-rhythm-2, .5rem));background:var(--fk-sidebar-nav-flyout-bg, var(--fk-color-surface, #ffffff));border:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef));border-radius:var(--fk-sidebar-nav-flyout-radius, var(--fk-radius-md, .75rem));box-shadow:var(--fk-sidebar-nav-flyout-shadow, var(--fk-shadow-lg, 0 18px 44px -14px rgba(20, 34, 80, .3)))}.fk-sidebar-nav__flyout-panel:before{content:\"\";position:absolute;left:-.375rem;top:var(--fk-sidebar-nav-flyout-caret-top, 1.375rem);width:.6875rem;height:.6875rem;background:var(--fk-sidebar-nav-flyout-bg, var(--fk-color-surface, #ffffff));border-left:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef));border-bottom:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef));transform:rotate(45deg)}.fk-sidebar-nav__flyout-items{display:flex;flex:1 1 auto;flex-direction:column;gap:var(--fk-sidebar-nav-flyout-gap, var(--fk-rhythm-1, .25rem));min-height:0;overflow-y:auto;overscroll-behavior:contain;padding-inline:var(--fk-focus-ring-width, 3px);margin-inline:calc(var(--fk-focus-ring-width, 3px) * -1)}.fk-sidebar-nav__flyout-head{display:flex;flex-shrink:0;align-items:center;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));padding:.4375rem var(--fk-rhythm-3, .625rem) .5625rem;border-bottom:var(--fk-border-width, 1px) solid var(--fk-sidebar-nav-flyout-border, var(--fk-color-border, #e5e8ef))}.fk-sidebar-nav__flyout-icon{flex:none;display:grid;place-items:center;width:1.5rem;height:1.5rem;border-radius:var(--fk-sidebar-nav-flyout-icon-radius, var(--fk-radius-sm, .5rem));color:var(--fk-sidebar-nav-branch-color, var(--fk-color-primary, #2348e0));background:var(--fk-sidebar-nav-branch-bg, var(--fk-color-primary-light, #eef2fe))}.fk-sidebar-nav__flyout-title{min-width:0;overflow:hidden;font-family:var(--fk-sidebar-nav-flyout-title-font-family, var(--fk-font-family-display, var(--fk-font-family-base)));font-size:var(--fk-sidebar-nav-flyout-title-font-size, .84375rem);font-weight:var(--fk-sidebar-nav-flyout-title-font-weight, var(--fk-font-weight-semibold, 600));white-space:nowrap;text-overflow:ellipsis;color:var(--fk-sidebar-nav-flyout-title-color, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__flyout-subgroup{display:block;flex-shrink:0;padding:var(--fk-rhythm-2, .5rem) var(--fk-rhythm-3, .75rem) var(--fk-rhythm-1, .25rem);font-family:var(--fk-sidebar-nav-subgroup-font-family, var(--fk-font-family-mono));font-size:var(--fk-sidebar-nav-subgroup-font-size, .625rem);font-weight:var(--fk-sidebar-nav-subgroup-font-weight, var(--fk-font-weight-semibold, 600));letter-spacing:.12em;text-transform:uppercase;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--fk-sidebar-nav-subgroup-color, var(--fk-color-muted, #8a93a8))}.fk-sidebar-nav__flyout-item{box-sizing:border-box;display:flex;align-items:center;width:100%;margin:0;gap:var(--fk-sidebar-nav-row-gap, var(--fk-rhythm-2, .5rem));padding:var(--fk-sidebar-nav-row-padding-block, var(--fk-rhythm-2, .5rem)) var(--fk-sidebar-nav-row-padding-inline, var(--fk-rhythm-3, .75rem));border-radius:var(--fk-sidebar-nav-row-radius, var(--fk-radius-md, .5rem));font-size:var(--fk-sidebar-nav-row-font-size, .875rem);font-weight:var(--fk-sidebar-nav-row-font-weight, var(--fk-font-weight-medium, 500));color:var(--fk-sidebar-nav-row-color, var(--fk-color-muted, #36405a));text-decoration:none;white-space:nowrap;cursor:pointer;transition:background-color .12s ease,color .12s ease}.fk-sidebar-nav__flyout-item:hover{background:var(--fk-sidebar-nav-row-bg-hover, var(--fk-color-surface-muted, #f5f6fa));color:var(--fk-sidebar-nav-row-color-hover, var(--fk-color-text, #0e1526))}.fk-sidebar-nav__flyout-item:focus-visible{outline:none;box-shadow:var(--fk-sidebar-nav-focus-ring, var(--fk-focus-ring, 0 0 0 3px rgba(35, 72, 224, .28)))}.fk-sidebar-nav__flyout-item--active,.fk-sidebar-nav__flyout-item--active:hover{background:var(--fk-sidebar-nav-row-bg-active, var(--fk-color-primary, #2348e0));color:var(--fk-sidebar-nav-row-color-active, #ffffff);font-weight:var(--fk-sidebar-nav-child-font-weight-active, var(--fk-font-weight-semibold, 600))}\n"] }]
|
|
706
706
|
}], ctorParameters: () => [], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }], collapsed: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsed", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], flyoutTpl: [{ type: i0.ViewChild, args: ['flyoutTpl', { isSignal: true }] }], itemTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => SidebarNavItemDirective), { isSignal: true }] }], hostClass: [{
|
|
707
707
|
type: HostBinding,
|
|
708
708
|
args: ['class']
|
|
@@ -2191,6 +2191,114 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2191
2191
|
args: ['attr.id']
|
|
2192
2192
|
}] } });
|
|
2193
2193
|
|
|
2194
|
+
/**
|
|
2195
|
+
* The chrome of a signed-in dashboard, built on `fk-app-shell`: a full-height
|
|
2196
|
+
* aside with a brand header and collapse toggle, a sticky frosted topbar with
|
|
2197
|
+
* a mobile hamburger, a capped page area with an optional loading veil, and a
|
|
2198
|
+
* footer. Every dashboard that uses it gets the identical structure — the
|
|
2199
|
+
* same hamburger, the same collapse, the same scroll behaviour — and differs
|
|
2200
|
+
* only in what it projects.
|
|
2201
|
+
*
|
|
2202
|
+
* <fk-dashboard-layout [pageLoading]="navigating()">
|
|
2203
|
+
* <fk-nav-brand layoutBrand brandText="Acme" />
|
|
2204
|
+
* <fk-dashboard-nav layoutAside [groups]="groups()" [collapsed]="collapsed()" />
|
|
2205
|
+
* <nav layoutTopbarStart>Acme / Overview</nav>
|
|
2206
|
+
* <fk-user-menu layoutTopbarEnd … />
|
|
2207
|
+
* <router-outlet />
|
|
2208
|
+
* <span layoutFooter>© Acme</span>
|
|
2209
|
+
* </fk-dashboard-layout>
|
|
2210
|
+
*
|
|
2211
|
+
* A dashboard that needs a trailing panel — a documentation reader, a detail
|
|
2212
|
+
* inspector — projects it into `[layoutEnd]` and chooses its `endMode`. One
|
|
2213
|
+
* that needs a panel beside the page, such as a secondary navigation, projects
|
|
2214
|
+
* it into `[layoutContentPanel]`, which sits in the content row ahead of the
|
|
2215
|
+
* scroll container so the page scrolls under it rather than with it.
|
|
2216
|
+
*
|
|
2217
|
+
* The aside's toggle and the topbar's hamburger drive the underlying shell;
|
|
2218
|
+
* `collapsed` reports the rail state so projected controls can follow it.
|
|
2219
|
+
* The toggle glyphs are projection slots with a built-in fallback, so no icon
|
|
2220
|
+
* registry is required.
|
|
2221
|
+
*/
|
|
2222
|
+
class DashboardLayoutComponent {
|
|
2223
|
+
// ===== INPUTS =====
|
|
2224
|
+
/** Passed to `fk-app-shell`. `icon` collapses to a rail; `side` hides entirely. */
|
|
2225
|
+
mode = input('icon', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
2226
|
+
sidenavWidth = input('260px', ...(ngDevMode ? [{ debugName: "sidenavWidth" }] : /* istanbul ignore next */ []));
|
|
2227
|
+
collapsedWidth = input('64px', ...(ngDevMode ? [{ debugName: "collapsedWidth" }] : /* istanbul ignore next */ []));
|
|
2228
|
+
/** Layout mode for the trailing panel, when `[layoutEnd]` is projected. */
|
|
2229
|
+
endMode = input('over', ...(ngDevMode ? [{ debugName: "endMode" }] : /* istanbul ignore next */ []));
|
|
2230
|
+
endWidth = input('400px', ...(ngDevMode ? [{ debugName: "endWidth" }] : /* istanbul ignore next */ []));
|
|
2231
|
+
endCollapsedWidth = input('64px', ...(ngDevMode ? [{ debugName: "endCollapsedWidth" }] : /* istanbul ignore next */ []));
|
|
2232
|
+
/** Veil the page area with the projected `[layoutPageLoader]` content. */
|
|
2233
|
+
pageLoading = input(false, ...(ngDevMode ? [{ debugName: "pageLoading" }] : /* istanbul ignore next */ []));
|
|
2234
|
+
/** Accessible name for the aside's collapse toggle. */
|
|
2235
|
+
toggleAriaLabel = input('Toggle navigation', ...(ngDevMode ? [{ debugName: "toggleAriaLabel" }] : /* istanbul ignore next */ []));
|
|
2236
|
+
/** Accessible name for the topbar's mobile hamburger. */
|
|
2237
|
+
menuAriaLabel = input('Open navigation', ...(ngDevMode ? [{ debugName: "menuAriaLabel" }] : /* istanbul ignore next */ []));
|
|
2238
|
+
// ===== BASE PROPS =====
|
|
2239
|
+
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
2240
|
+
id = input(null, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
2241
|
+
// ===== COMPUTED =====
|
|
2242
|
+
shell = viewChild(AppShellComponent, ...(ngDevMode ? [{ debugName: "shell" }] : /* istanbul ignore next */ []));
|
|
2243
|
+
/** Whether the aside is in its icon rail. Projected controls follow this. */
|
|
2244
|
+
collapsed = computed(() => this.shell()?.isCollapsed() ?? false, ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
|
|
2245
|
+
/** Whether the trailing panel is showing. Projected controls follow this. */
|
|
2246
|
+
endOpen = computed(() => this.shell()?.endOpen() ?? false, ...(ngDevMode ? [{ debugName: "endOpen" }] : /* istanbul ignore next */ []));
|
|
2247
|
+
classes = computed(() => [
|
|
2248
|
+
'fk-dashboard-layout',
|
|
2249
|
+
this.collapsed() ? 'fk-dashboard-layout--collapsed' : '',
|
|
2250
|
+
this.pageLoading() ? 'fk-dashboard-layout--page-loading' : '',
|
|
2251
|
+
this.className(),
|
|
2252
|
+
]
|
|
2253
|
+
.filter(Boolean)
|
|
2254
|
+
.join(' '), ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
2255
|
+
get hostClass() {
|
|
2256
|
+
return this.classes();
|
|
2257
|
+
}
|
|
2258
|
+
get hostId() {
|
|
2259
|
+
return this.id();
|
|
2260
|
+
}
|
|
2261
|
+
/** The aside header's toggle: collapse or expand the rail. */
|
|
2262
|
+
toggleSidenav() {
|
|
2263
|
+
this.shell()?.toggleSidenav();
|
|
2264
|
+
}
|
|
2265
|
+
/** The topbar hamburger: open the off-canvas aside on narrow viewports. */
|
|
2266
|
+
openSidenav() {
|
|
2267
|
+
this.shell()?.openSidenav();
|
|
2268
|
+
}
|
|
2269
|
+
/**
|
|
2270
|
+
* Collapse the rail from outside the header's own toggle — what a dashboard
|
|
2271
|
+
* calls when it opens the trailing panel and wants the room.
|
|
2272
|
+
*/
|
|
2273
|
+
closeSidenav() {
|
|
2274
|
+
this.shell()?.closeSidenav();
|
|
2275
|
+
}
|
|
2276
|
+
/** Show the projected `[layoutEnd]` panel. */
|
|
2277
|
+
openEnd() {
|
|
2278
|
+
this.shell()?.openEnd();
|
|
2279
|
+
}
|
|
2280
|
+
/** Hide it. */
|
|
2281
|
+
closeEnd() {
|
|
2282
|
+
this.shell()?.closeEnd();
|
|
2283
|
+
}
|
|
2284
|
+
/** Hide it if it is showing, show it if it is not. */
|
|
2285
|
+
toggleEnd() {
|
|
2286
|
+
this.shell()?.toggleEnd();
|
|
2287
|
+
}
|
|
2288
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DashboardLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2289
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DashboardLayoutComponent, isStandalone: true, selector: "fk-dashboard-layout", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, sidenavWidth: { classPropertyName: "sidenavWidth", publicName: "sidenavWidth", isSignal: true, isRequired: false, transformFunction: null }, collapsedWidth: { classPropertyName: "collapsedWidth", publicName: "collapsedWidth", isSignal: true, isRequired: false, transformFunction: null }, endMode: { classPropertyName: "endMode", publicName: "endMode", isSignal: true, isRequired: false, transformFunction: null }, endWidth: { classPropertyName: "endWidth", publicName: "endWidth", isSignal: true, isRequired: false, transformFunction: null }, endCollapsedWidth: { classPropertyName: "endCollapsedWidth", publicName: "endCollapsedWidth", isSignal: true, isRequired: false, transformFunction: null }, pageLoading: { classPropertyName: "pageLoading", publicName: "pageLoading", isSignal: true, isRequired: false, transformFunction: null }, toggleAriaLabel: { classPropertyName: "toggleAriaLabel", publicName: "toggleAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, menuAriaLabel: { classPropertyName: "menuAriaLabel", publicName: "menuAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass", "attr.id": "this.hostId" } }, viewQueries: [{ propertyName: "shell", first: true, predicate: AppShellComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!--\n Banners sit above the shell, in flow, inside the fixed-height host: the\n shell absorbs whatever height they leave, so a banner appearing never adds a\n document scrollbar.\n-->\n<ng-content select=\"[layoutBanner]\" />\n\n<fk-app-shell\n [mode]=\"mode()\"\n [sidenavWidth]=\"sidenavWidth()\"\n [collapsedWidth]=\"collapsedWidth()\"\n [endMode]=\"endMode()\"\n [endWidth]=\"endWidth()\"\n [endCollapsedWidth]=\"endCollapsedWidth()\"\n>\n <div appShellSidenav class=\"fk-dashboard-layout__aside\">\n <div class=\"fk-dashboard-layout__aside-header\">\n <div class=\"fk-dashboard-layout__brand\">\n <ng-content select=\"[layoutBrand]\" />\n </div>\n\n <button\n type=\"button\"\n class=\"fk-dashboard-layout__toggle\"\n [attr.aria-label]=\"toggleAriaLabel()\"\n [attr.aria-expanded]=\"!collapsed()\"\n (click)=\"toggleSidenav()\"\n >\n <ng-content select=\"[layoutToggleIcon]\" />\n </button>\n </div>\n\n <div class=\"fk-dashboard-layout__aside-body\">\n <ng-content select=\"[layoutAside]\" />\n </div>\n\n <div class=\"fk-dashboard-layout__aside-footer\">\n <ng-content select=\"[layoutAsideFooter]\" />\n </div>\n </div>\n\n <div appShellContent class=\"fk-dashboard-layout__content\">\n <!--\n A panel beside the page \u2014 a secondary navigation, a filter rail \u2014 sits in\n the content row ahead of the scroll container, so the topbar and the page\n scroll under it rather than it scrolling with them.\n -->\n <ng-content select=\"[layoutContentPanel]\" />\n\n <!--\n The scroll container. The topbar sticks at its top and the page scrolls\n under it, which is what lets the frosted bar show content through.\n -->\n <div class=\"fk-dashboard-layout__body\">\n <header class=\"fk-dashboard-layout__topbar\">\n <div class=\"fk-dashboard-layout__topbar-inner\">\n <button\n type=\"button\"\n class=\"fk-dashboard-layout__menu\"\n [attr.aria-label]=\"menuAriaLabel()\"\n (click)=\"openSidenav()\"\n >\n <ng-content select=\"[layoutMenuIcon]\" />\n </button>\n\n <div class=\"fk-dashboard-layout__topbar-start\">\n <ng-content select=\"[layoutTopbarStart]\" />\n </div>\n\n <div class=\"fk-dashboard-layout__topbar-end\">\n <ng-content select=\"[layoutTopbarEnd]\" />\n </div>\n </div>\n </header>\n\n <div class=\"fk-dashboard-layout__page\">\n <ng-content />\n\n @if (pageLoading()) {\n <div class=\"fk-dashboard-layout__page-loader\" aria-live=\"polite\">\n <ng-content select=\"[layoutPageLoader]\" />\n </div>\n }\n </div>\n </div>\n </div>\n\n <!--\n A plain div, not a second `aside`: `fk-app-shell` already makes its end\n region an aside, and nesting one inside it would declare two landmarks for\n one panel.\n -->\n <div appShellEnd class=\"fk-dashboard-layout__end\">\n <ng-content select=\"[layoutEnd]\" />\n </div>\n\n <footer appShellFooter class=\"fk-dashboard-layout__footer\">\n <ng-content select=\"[layoutFooter]\" />\n </footer>\n</fk-app-shell>\n", styles: [":host{display:flex;flex-direction:column;height:var(--fk-dashboard-layout-height, 100vh);overflow:hidden;--_max-width: var(--fk-dashboard-layout-max-width, 1400px);--_topbar-height: var(--fk-dashboard-layout-topbar-height, 4rem)}fk-app-shell{flex:1;min-height:0}.fk-dashboard-layout__aside{display:flex;flex-direction:column;height:100%;background:var(--fk-dashboard-layout-aside-bg, var(--fk-color-surface, #ffffff));border-right:1px solid var(--fk-dashboard-layout-aside-border-color, var(--fk-color-border, #d9e2ee))}.fk-dashboard-layout__aside-header{display:flex;align-items:center;gap:var(--fk-rhythm-2, .5rem);flex-shrink:0;padding:var(--fk-dashboard-layout-aside-header-padding, var(--fk-rhythm-4, 1rem) var(--fk-rhythm-5, 1.25rem))}.fk-dashboard-layout__brand{flex:1 1 auto;min-width:0;display:flex;align-items:center}.fk-dashboard-layout__aside-body{flex:1;min-height:0;overflow-y:auto}.fk-dashboard-layout__aside-footer{flex-shrink:0}.fk-dashboard-layout__aside-footer:empty{display:none}.fk-dashboard-layout__toggle,.fk-dashboard-layout__menu{display:grid;place-items:center;flex:none;padding:0;border:1px solid transparent;border-radius:var(--fk-radius-sm, .25rem);background:none;color:var(--fk-dashboard-layout-toggle-color, var(--fk-color-muted, #8a98a8));cursor:pointer;transition:border-color .15s,background-color .15s,color .15s}.fk-dashboard-layout__toggle:hover,.fk-dashboard-layout__menu:hover{border-color:var(--fk-dashboard-layout-toggle-hover-border-color, var(--fk-color-border, #d9e2ee));background:var(--fk-dashboard-layout-toggle-hover-bg, var(--fk-color-surface, #ffffff));color:var(--fk-dashboard-layout-toggle-hover-color, var(--fk-color-text, #1f2d3d))}.fk-dashboard-layout__toggle:focus-visible,.fk-dashboard-layout__menu:focus-visible{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-dashboard-layout__toggle:not(:has(*)):before,.fk-dashboard-layout__menu:not(:has(*)):before{content:\"\";width:1rem;height:.75rem;background:linear-gradient(currentColor 0 2px,transparent 2px 5px,currentColor 5px 7px,transparent 7px 10px,currentColor 10px 12px)}.fk-dashboard-layout__toggle{width:var(--fk-dashboard-layout-toggle-size, 2rem);height:var(--fk-dashboard-layout-toggle-size, 2rem)}.fk-dashboard-layout__menu{width:var(--fk-dashboard-layout-menu-size, 2.25rem);height:var(--fk-dashboard-layout-menu-size, 2.25rem)}.fk-dashboard-layout__content{display:flex;flex-direction:column;height:100%;min-height:0}.fk-dashboard-layout__content:has(>:not(.fk-dashboard-layout__body)){flex-direction:row;width:100%}.fk-dashboard-layout__body{flex:1;min-width:0;min-height:0;overflow-y:auto;overscroll-behavior:contain}.fk-dashboard-layout__topbar{position:sticky;top:0;z-index:20;height:var(--_topbar-height);background:var(--fk-dashboard-layout-topbar-bg, rgba(251, 251, 253, .82));backdrop-filter:blur(var(--fk-dashboard-layout-topbar-blur, 14px));-webkit-backdrop-filter:blur(var(--fk-dashboard-layout-topbar-blur, 14px));border-bottom:1px solid var(--fk-dashboard-layout-topbar-border-color, var(--fk-color-border, #d9e2ee))}.fk-dashboard-layout__topbar-inner{display:flex;align-items:center;gap:var(--fk-rhythm-4, 1rem);height:100%;max-width:var(--_max-width);margin-inline:auto;padding-inline:var(--fk-dashboard-layout-topbar-padding-inline, var(--fk-rhythm-8, 2rem))}.fk-dashboard-layout__topbar-start{display:flex;align-items:center;min-width:0}.fk-dashboard-layout__topbar-end{display:flex;align-items:center;gap:var(--fk-rhythm-3, .75rem);margin-left:auto}.fk-dashboard-layout__menu{display:none}.fk-dashboard-layout__end{display:flex;flex-direction:column;height:100%;min-height:0}.fk-dashboard-layout__end:empty{display:none}.fk-dashboard-layout__page{container-type:inline-size;position:relative;max-width:var(--_max-width);margin-inline:auto;padding:var(--fk-dashboard-layout-page-padding, var(--fk-rhythm-4, 1rem));min-height:calc(100% - var(--_topbar-height))}.fk-dashboard-layout__page-loader{position:absolute;inset:0;z-index:10;display:flex;align-items:center;justify-content:center;min-height:12rem;background:var(--fk-dashboard-layout-page-loader-bg, color-mix(in srgb, var(--fk-color-bg, #fbfbfd) 72%, transparent));backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fk-dashboard-layout__footer{position:relative;z-index:100;display:flex;align-items:center;justify-content:center;flex-shrink:0;height:var(--fk-dashboard-layout-footer-height, 2.5rem);background:var(--fk-dashboard-layout-footer-bg, var(--fk-color-surface, #ffffff));border-top:1px solid var(--fk-dashboard-layout-footer-border-color, var(--fk-color-border, #d9e2ee));font-family:var(--fk-dashboard-layout-footer-font-family, var(--fk-font-family-base, sans-serif));font-size:var(--fk-dashboard-layout-footer-font-size, var(--fk-typography-small-font-size, .75rem));color:var(--fk-dashboard-layout-footer-color, var(--fk-color-muted, #8a98a8))}.fk-dashboard-layout__footer:empty{display:none}:host(.fk-dashboard-layout--collapsed) .fk-dashboard-layout__aside-header{justify-content:center;padding-inline:0}:host(.fk-dashboard-layout--collapsed) .fk-dashboard-layout__brand{display:none}@media(min-width:48em){.fk-dashboard-layout__page{padding:var(--fk-dashboard-layout-page-padding-wide, var(--fk-rhythm-6, 1.5rem) var(--fk-rhythm-8, 2rem))}}@media(max-width:760px){.fk-dashboard-layout__menu{display:grid}.fk-dashboard-layout__topbar-inner{padding-inline:var(--fk-rhythm-4, 1rem)}}@media(prefers-reduced-motion:reduce){.fk-dashboard-layout__toggle,.fk-dashboard-layout__menu{transition:none}}\n"], dependencies: [{ kind: "component", type: AppShellComponent, selector: "fk-app-shell", inputs: ["mode", "sidenavWidth", "collapsedWidth", "breakpoint", "sticky", "collapseOnMobile", "endMode", "endWidth", "endCollapsedWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2290
|
+
}
|
|
2291
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DashboardLayoutComponent, decorators: [{
|
|
2292
|
+
type: Component,
|
|
2293
|
+
args: [{ selector: 'fk-dashboard-layout', standalone: true, imports: [AppShellComponent], encapsulation: ViewEncapsulation.Emulated, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n Banners sit above the shell, in flow, inside the fixed-height host: the\n shell absorbs whatever height they leave, so a banner appearing never adds a\n document scrollbar.\n-->\n<ng-content select=\"[layoutBanner]\" />\n\n<fk-app-shell\n [mode]=\"mode()\"\n [sidenavWidth]=\"sidenavWidth()\"\n [collapsedWidth]=\"collapsedWidth()\"\n [endMode]=\"endMode()\"\n [endWidth]=\"endWidth()\"\n [endCollapsedWidth]=\"endCollapsedWidth()\"\n>\n <div appShellSidenav class=\"fk-dashboard-layout__aside\">\n <div class=\"fk-dashboard-layout__aside-header\">\n <div class=\"fk-dashboard-layout__brand\">\n <ng-content select=\"[layoutBrand]\" />\n </div>\n\n <button\n type=\"button\"\n class=\"fk-dashboard-layout__toggle\"\n [attr.aria-label]=\"toggleAriaLabel()\"\n [attr.aria-expanded]=\"!collapsed()\"\n (click)=\"toggleSidenav()\"\n >\n <ng-content select=\"[layoutToggleIcon]\" />\n </button>\n </div>\n\n <div class=\"fk-dashboard-layout__aside-body\">\n <ng-content select=\"[layoutAside]\" />\n </div>\n\n <div class=\"fk-dashboard-layout__aside-footer\">\n <ng-content select=\"[layoutAsideFooter]\" />\n </div>\n </div>\n\n <div appShellContent class=\"fk-dashboard-layout__content\">\n <!--\n A panel beside the page \u2014 a secondary navigation, a filter rail \u2014 sits in\n the content row ahead of the scroll container, so the topbar and the page\n scroll under it rather than it scrolling with them.\n -->\n <ng-content select=\"[layoutContentPanel]\" />\n\n <!--\n The scroll container. The topbar sticks at its top and the page scrolls\n under it, which is what lets the frosted bar show content through.\n -->\n <div class=\"fk-dashboard-layout__body\">\n <header class=\"fk-dashboard-layout__topbar\">\n <div class=\"fk-dashboard-layout__topbar-inner\">\n <button\n type=\"button\"\n class=\"fk-dashboard-layout__menu\"\n [attr.aria-label]=\"menuAriaLabel()\"\n (click)=\"openSidenav()\"\n >\n <ng-content select=\"[layoutMenuIcon]\" />\n </button>\n\n <div class=\"fk-dashboard-layout__topbar-start\">\n <ng-content select=\"[layoutTopbarStart]\" />\n </div>\n\n <div class=\"fk-dashboard-layout__topbar-end\">\n <ng-content select=\"[layoutTopbarEnd]\" />\n </div>\n </div>\n </header>\n\n <div class=\"fk-dashboard-layout__page\">\n <ng-content />\n\n @if (pageLoading()) {\n <div class=\"fk-dashboard-layout__page-loader\" aria-live=\"polite\">\n <ng-content select=\"[layoutPageLoader]\" />\n </div>\n }\n </div>\n </div>\n </div>\n\n <!--\n A plain div, not a second `aside`: `fk-app-shell` already makes its end\n region an aside, and nesting one inside it would declare two landmarks for\n one panel.\n -->\n <div appShellEnd class=\"fk-dashboard-layout__end\">\n <ng-content select=\"[layoutEnd]\" />\n </div>\n\n <footer appShellFooter class=\"fk-dashboard-layout__footer\">\n <ng-content select=\"[layoutFooter]\" />\n </footer>\n</fk-app-shell>\n", styles: [":host{display:flex;flex-direction:column;height:var(--fk-dashboard-layout-height, 100vh);overflow:hidden;--_max-width: var(--fk-dashboard-layout-max-width, 1400px);--_topbar-height: var(--fk-dashboard-layout-topbar-height, 4rem)}fk-app-shell{flex:1;min-height:0}.fk-dashboard-layout__aside{display:flex;flex-direction:column;height:100%;background:var(--fk-dashboard-layout-aside-bg, var(--fk-color-surface, #ffffff));border-right:1px solid var(--fk-dashboard-layout-aside-border-color, var(--fk-color-border, #d9e2ee))}.fk-dashboard-layout__aside-header{display:flex;align-items:center;gap:var(--fk-rhythm-2, .5rem);flex-shrink:0;padding:var(--fk-dashboard-layout-aside-header-padding, var(--fk-rhythm-4, 1rem) var(--fk-rhythm-5, 1.25rem))}.fk-dashboard-layout__brand{flex:1 1 auto;min-width:0;display:flex;align-items:center}.fk-dashboard-layout__aside-body{flex:1;min-height:0;overflow-y:auto}.fk-dashboard-layout__aside-footer{flex-shrink:0}.fk-dashboard-layout__aside-footer:empty{display:none}.fk-dashboard-layout__toggle,.fk-dashboard-layout__menu{display:grid;place-items:center;flex:none;padding:0;border:1px solid transparent;border-radius:var(--fk-radius-sm, .25rem);background:none;color:var(--fk-dashboard-layout-toggle-color, var(--fk-color-muted, #8a98a8));cursor:pointer;transition:border-color .15s,background-color .15s,color .15s}.fk-dashboard-layout__toggle:hover,.fk-dashboard-layout__menu:hover{border-color:var(--fk-dashboard-layout-toggle-hover-border-color, var(--fk-color-border, #d9e2ee));background:var(--fk-dashboard-layout-toggle-hover-bg, var(--fk-color-surface, #ffffff));color:var(--fk-dashboard-layout-toggle-hover-color, var(--fk-color-text, #1f2d3d))}.fk-dashboard-layout__toggle:focus-visible,.fk-dashboard-layout__menu:focus-visible{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-dashboard-layout__toggle:not(:has(*)):before,.fk-dashboard-layout__menu:not(:has(*)):before{content:\"\";width:1rem;height:.75rem;background:linear-gradient(currentColor 0 2px,transparent 2px 5px,currentColor 5px 7px,transparent 7px 10px,currentColor 10px 12px)}.fk-dashboard-layout__toggle{width:var(--fk-dashboard-layout-toggle-size, 2rem);height:var(--fk-dashboard-layout-toggle-size, 2rem)}.fk-dashboard-layout__menu{width:var(--fk-dashboard-layout-menu-size, 2.25rem);height:var(--fk-dashboard-layout-menu-size, 2.25rem)}.fk-dashboard-layout__content{display:flex;flex-direction:column;height:100%;min-height:0}.fk-dashboard-layout__content:has(>:not(.fk-dashboard-layout__body)){flex-direction:row;width:100%}.fk-dashboard-layout__body{flex:1;min-width:0;min-height:0;overflow-y:auto;overscroll-behavior:contain}.fk-dashboard-layout__topbar{position:sticky;top:0;z-index:20;height:var(--_topbar-height);background:var(--fk-dashboard-layout-topbar-bg, rgba(251, 251, 253, .82));backdrop-filter:blur(var(--fk-dashboard-layout-topbar-blur, 14px));-webkit-backdrop-filter:blur(var(--fk-dashboard-layout-topbar-blur, 14px));border-bottom:1px solid var(--fk-dashboard-layout-topbar-border-color, var(--fk-color-border, #d9e2ee))}.fk-dashboard-layout__topbar-inner{display:flex;align-items:center;gap:var(--fk-rhythm-4, 1rem);height:100%;max-width:var(--_max-width);margin-inline:auto;padding-inline:var(--fk-dashboard-layout-topbar-padding-inline, var(--fk-rhythm-8, 2rem))}.fk-dashboard-layout__topbar-start{display:flex;align-items:center;min-width:0}.fk-dashboard-layout__topbar-end{display:flex;align-items:center;gap:var(--fk-rhythm-3, .75rem);margin-left:auto}.fk-dashboard-layout__menu{display:none}.fk-dashboard-layout__end{display:flex;flex-direction:column;height:100%;min-height:0}.fk-dashboard-layout__end:empty{display:none}.fk-dashboard-layout__page{container-type:inline-size;position:relative;max-width:var(--_max-width);margin-inline:auto;padding:var(--fk-dashboard-layout-page-padding, var(--fk-rhythm-4, 1rem));min-height:calc(100% - var(--_topbar-height))}.fk-dashboard-layout__page-loader{position:absolute;inset:0;z-index:10;display:flex;align-items:center;justify-content:center;min-height:12rem;background:var(--fk-dashboard-layout-page-loader-bg, color-mix(in srgb, var(--fk-color-bg, #fbfbfd) 72%, transparent));backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fk-dashboard-layout__footer{position:relative;z-index:100;display:flex;align-items:center;justify-content:center;flex-shrink:0;height:var(--fk-dashboard-layout-footer-height, 2.5rem);background:var(--fk-dashboard-layout-footer-bg, var(--fk-color-surface, #ffffff));border-top:1px solid var(--fk-dashboard-layout-footer-border-color, var(--fk-color-border, #d9e2ee));font-family:var(--fk-dashboard-layout-footer-font-family, var(--fk-font-family-base, sans-serif));font-size:var(--fk-dashboard-layout-footer-font-size, var(--fk-typography-small-font-size, .75rem));color:var(--fk-dashboard-layout-footer-color, var(--fk-color-muted, #8a98a8))}.fk-dashboard-layout__footer:empty{display:none}:host(.fk-dashboard-layout--collapsed) .fk-dashboard-layout__aside-header{justify-content:center;padding-inline:0}:host(.fk-dashboard-layout--collapsed) .fk-dashboard-layout__brand{display:none}@media(min-width:48em){.fk-dashboard-layout__page{padding:var(--fk-dashboard-layout-page-padding-wide, var(--fk-rhythm-6, 1.5rem) var(--fk-rhythm-8, 2rem))}}@media(max-width:760px){.fk-dashboard-layout__menu{display:grid}.fk-dashboard-layout__topbar-inner{padding-inline:var(--fk-rhythm-4, 1rem)}}@media(prefers-reduced-motion:reduce){.fk-dashboard-layout__toggle,.fk-dashboard-layout__menu{transition:none}}\n"] }]
|
|
2294
|
+
}], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], sidenavWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidenavWidth", required: false }] }], collapsedWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsedWidth", required: false }] }], endMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "endMode", required: false }] }], endWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "endWidth", required: false }] }], endCollapsedWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "endCollapsedWidth", required: false }] }], pageLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageLoading", required: false }] }], toggleAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "toggleAriaLabel", required: false }] }], menuAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuAriaLabel", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], shell: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AppShellComponent), { isSignal: true }] }], hostClass: [{
|
|
2295
|
+
type: HostBinding,
|
|
2296
|
+
args: ['class']
|
|
2297
|
+
}], hostId: [{
|
|
2298
|
+
type: HostBinding,
|
|
2299
|
+
args: ['attr.id']
|
|
2300
|
+
}] } });
|
|
2301
|
+
|
|
2194
2302
|
/**
|
|
2195
2303
|
* A dashboard's sidebar navigation: the caller's groups, with items the
|
|
2196
2304
|
* caller may not open already removed, rendered as one `fk-sidebar-nav` per
|
|
@@ -2236,10 +2344,20 @@ class DashboardNavComponent {
|
|
|
2236
2344
|
id = input(null, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
2237
2345
|
ariaLabel = input(null, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
2238
2346
|
// ===== INJECTED =====
|
|
2347
|
+
// The layout first, and it matters which: `fk-app-shell` sits inside
|
|
2348
|
+
// `fk-dashboard-layout`'s own template, so a nav projected into the
|
|
2349
|
+
// layout is declared outside the shell and can never inject it. The
|
|
2350
|
+
// layout is the ancestor it is actually written inside.
|
|
2351
|
+
layout = inject(DashboardLayoutComponent, {
|
|
2352
|
+
optional: true,
|
|
2353
|
+
});
|
|
2239
2354
|
shell = inject(AppShellComponent, { optional: true });
|
|
2240
2355
|
// ===== COMPUTED =====
|
|
2241
|
-
/** The rail state in force: this input, else
|
|
2242
|
-
isCollapsed = computed(() => this.collapsed() ??
|
|
2356
|
+
/** The rail state in force: this input, else whichever ancestor owns it. */
|
|
2357
|
+
isCollapsed = computed(() => this.collapsed() ??
|
|
2358
|
+
this.layout?.collapsed() ??
|
|
2359
|
+
this.shell?.isCollapsed() ??
|
|
2360
|
+
false, ...(ngDevMode ? [{ debugName: "isCollapsed" }] : /* istanbul ignore next */ []));
|
|
2243
2361
|
/**
|
|
2244
2362
|
* Visible groups sliced into render segments, each carrying a single-group
|
|
2245
2363
|
* `SidebarNavModel`.
|
|
@@ -2343,114 +2461,6 @@ function toModelItem(item) {
|
|
|
2343
2461
|
};
|
|
2344
2462
|
}
|
|
2345
2463
|
|
|
2346
|
-
/**
|
|
2347
|
-
* The chrome of a signed-in dashboard, built on `fk-app-shell`: a full-height
|
|
2348
|
-
* aside with a brand header and collapse toggle, a sticky frosted topbar with
|
|
2349
|
-
* a mobile hamburger, a capped page area with an optional loading veil, and a
|
|
2350
|
-
* footer. Every dashboard that uses it gets the identical structure — the
|
|
2351
|
-
* same hamburger, the same collapse, the same scroll behaviour — and differs
|
|
2352
|
-
* only in what it projects.
|
|
2353
|
-
*
|
|
2354
|
-
* <fk-dashboard-layout [pageLoading]="navigating()">
|
|
2355
|
-
* <fk-nav-brand layoutBrand brandText="Acme" />
|
|
2356
|
-
* <fk-dashboard-nav layoutAside [groups]="groups()" [collapsed]="collapsed()" />
|
|
2357
|
-
* <nav layoutTopbarStart>Acme / Overview</nav>
|
|
2358
|
-
* <fk-user-menu layoutTopbarEnd … />
|
|
2359
|
-
* <router-outlet />
|
|
2360
|
-
* <span layoutFooter>© Acme</span>
|
|
2361
|
-
* </fk-dashboard-layout>
|
|
2362
|
-
*
|
|
2363
|
-
* A dashboard that needs a trailing panel — a documentation reader, a detail
|
|
2364
|
-
* inspector — projects it into `[layoutEnd]` and chooses its `endMode`. One
|
|
2365
|
-
* that needs a panel beside the page, such as a secondary navigation, projects
|
|
2366
|
-
* it into `[layoutContentPanel]`, which sits in the content row ahead of the
|
|
2367
|
-
* scroll container so the page scrolls under it rather than with it.
|
|
2368
|
-
*
|
|
2369
|
-
* The aside's toggle and the topbar's hamburger drive the underlying shell;
|
|
2370
|
-
* `collapsed` reports the rail state so projected controls can follow it.
|
|
2371
|
-
* The toggle glyphs are projection slots with a built-in fallback, so no icon
|
|
2372
|
-
* registry is required.
|
|
2373
|
-
*/
|
|
2374
|
-
class DashboardLayoutComponent {
|
|
2375
|
-
// ===== INPUTS =====
|
|
2376
|
-
/** Passed to `fk-app-shell`. `icon` collapses to a rail; `side` hides entirely. */
|
|
2377
|
-
mode = input('icon', ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
2378
|
-
sidenavWidth = input('260px', ...(ngDevMode ? [{ debugName: "sidenavWidth" }] : /* istanbul ignore next */ []));
|
|
2379
|
-
collapsedWidth = input('64px', ...(ngDevMode ? [{ debugName: "collapsedWidth" }] : /* istanbul ignore next */ []));
|
|
2380
|
-
/** Layout mode for the trailing panel, when `[layoutEnd]` is projected. */
|
|
2381
|
-
endMode = input('over', ...(ngDevMode ? [{ debugName: "endMode" }] : /* istanbul ignore next */ []));
|
|
2382
|
-
endWidth = input('400px', ...(ngDevMode ? [{ debugName: "endWidth" }] : /* istanbul ignore next */ []));
|
|
2383
|
-
endCollapsedWidth = input('64px', ...(ngDevMode ? [{ debugName: "endCollapsedWidth" }] : /* istanbul ignore next */ []));
|
|
2384
|
-
/** Veil the page area with the projected `[layoutPageLoader]` content. */
|
|
2385
|
-
pageLoading = input(false, ...(ngDevMode ? [{ debugName: "pageLoading" }] : /* istanbul ignore next */ []));
|
|
2386
|
-
/** Accessible name for the aside's collapse toggle. */
|
|
2387
|
-
toggleAriaLabel = input('Toggle navigation', ...(ngDevMode ? [{ debugName: "toggleAriaLabel" }] : /* istanbul ignore next */ []));
|
|
2388
|
-
/** Accessible name for the topbar's mobile hamburger. */
|
|
2389
|
-
menuAriaLabel = input('Open navigation', ...(ngDevMode ? [{ debugName: "menuAriaLabel" }] : /* istanbul ignore next */ []));
|
|
2390
|
-
// ===== BASE PROPS =====
|
|
2391
|
-
className = input('', ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
2392
|
-
id = input(null, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
2393
|
-
// ===== COMPUTED =====
|
|
2394
|
-
shell = viewChild(AppShellComponent, ...(ngDevMode ? [{ debugName: "shell" }] : /* istanbul ignore next */ []));
|
|
2395
|
-
/** Whether the aside is in its icon rail. Projected controls follow this. */
|
|
2396
|
-
collapsed = computed(() => this.shell()?.isCollapsed() ?? false, ...(ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []));
|
|
2397
|
-
/** Whether the trailing panel is showing. Projected controls follow this. */
|
|
2398
|
-
endOpen = computed(() => this.shell()?.endOpen() ?? false, ...(ngDevMode ? [{ debugName: "endOpen" }] : /* istanbul ignore next */ []));
|
|
2399
|
-
classes = computed(() => [
|
|
2400
|
-
'fk-dashboard-layout',
|
|
2401
|
-
this.collapsed() ? 'fk-dashboard-layout--collapsed' : '',
|
|
2402
|
-
this.pageLoading() ? 'fk-dashboard-layout--page-loading' : '',
|
|
2403
|
-
this.className(),
|
|
2404
|
-
]
|
|
2405
|
-
.filter(Boolean)
|
|
2406
|
-
.join(' '), ...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
2407
|
-
get hostClass() {
|
|
2408
|
-
return this.classes();
|
|
2409
|
-
}
|
|
2410
|
-
get hostId() {
|
|
2411
|
-
return this.id();
|
|
2412
|
-
}
|
|
2413
|
-
/** The aside header's toggle: collapse or expand the rail. */
|
|
2414
|
-
toggleSidenav() {
|
|
2415
|
-
this.shell()?.toggleSidenav();
|
|
2416
|
-
}
|
|
2417
|
-
/** The topbar hamburger: open the off-canvas aside on narrow viewports. */
|
|
2418
|
-
openSidenav() {
|
|
2419
|
-
this.shell()?.openSidenav();
|
|
2420
|
-
}
|
|
2421
|
-
/**
|
|
2422
|
-
* Collapse the rail from outside the header's own toggle — what a dashboard
|
|
2423
|
-
* calls when it opens the trailing panel and wants the room.
|
|
2424
|
-
*/
|
|
2425
|
-
closeSidenav() {
|
|
2426
|
-
this.shell()?.closeSidenav();
|
|
2427
|
-
}
|
|
2428
|
-
/** Show the projected `[layoutEnd]` panel. */
|
|
2429
|
-
openEnd() {
|
|
2430
|
-
this.shell()?.openEnd();
|
|
2431
|
-
}
|
|
2432
|
-
/** Hide it. */
|
|
2433
|
-
closeEnd() {
|
|
2434
|
-
this.shell()?.closeEnd();
|
|
2435
|
-
}
|
|
2436
|
-
/** Hide it if it is showing, show it if it is not. */
|
|
2437
|
-
toggleEnd() {
|
|
2438
|
-
this.shell()?.toggleEnd();
|
|
2439
|
-
}
|
|
2440
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DashboardLayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2441
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DashboardLayoutComponent, isStandalone: true, selector: "fk-dashboard-layout", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, sidenavWidth: { classPropertyName: "sidenavWidth", publicName: "sidenavWidth", isSignal: true, isRequired: false, transformFunction: null }, collapsedWidth: { classPropertyName: "collapsedWidth", publicName: "collapsedWidth", isSignal: true, isRequired: false, transformFunction: null }, endMode: { classPropertyName: "endMode", publicName: "endMode", isSignal: true, isRequired: false, transformFunction: null }, endWidth: { classPropertyName: "endWidth", publicName: "endWidth", isSignal: true, isRequired: false, transformFunction: null }, endCollapsedWidth: { classPropertyName: "endCollapsedWidth", publicName: "endCollapsedWidth", isSignal: true, isRequired: false, transformFunction: null }, pageLoading: { classPropertyName: "pageLoading", publicName: "pageLoading", isSignal: true, isRequired: false, transformFunction: null }, toggleAriaLabel: { classPropertyName: "toggleAriaLabel", publicName: "toggleAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, menuAriaLabel: { classPropertyName: "menuAriaLabel", publicName: "menuAriaLabel", isSignal: true, isRequired: false, transformFunction: null }, className: { classPropertyName: "className", publicName: "className", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "this.hostClass", "attr.id": "this.hostId" } }, viewQueries: [{ propertyName: "shell", first: true, predicate: AppShellComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<!--\n Banners sit above the shell, in flow, inside the fixed-height host: the\n shell absorbs whatever height they leave, so a banner appearing never adds a\n document scrollbar.\n-->\n<ng-content select=\"[layoutBanner]\" />\n\n<fk-app-shell\n [mode]=\"mode()\"\n [sidenavWidth]=\"sidenavWidth()\"\n [collapsedWidth]=\"collapsedWidth()\"\n [endMode]=\"endMode()\"\n [endWidth]=\"endWidth()\"\n [endCollapsedWidth]=\"endCollapsedWidth()\"\n>\n <div appShellSidenav class=\"fk-dashboard-layout__aside\">\n <div class=\"fk-dashboard-layout__aside-header\">\n <div class=\"fk-dashboard-layout__brand\">\n <ng-content select=\"[layoutBrand]\" />\n </div>\n\n <button\n type=\"button\"\n class=\"fk-dashboard-layout__toggle\"\n [attr.aria-label]=\"toggleAriaLabel()\"\n [attr.aria-expanded]=\"!collapsed()\"\n (click)=\"toggleSidenav()\"\n >\n <ng-content select=\"[layoutToggleIcon]\" />\n </button>\n </div>\n\n <div class=\"fk-dashboard-layout__aside-body\">\n <ng-content select=\"[layoutAside]\" />\n </div>\n\n <div class=\"fk-dashboard-layout__aside-footer\">\n <ng-content select=\"[layoutAsideFooter]\" />\n </div>\n </div>\n\n <div appShellContent class=\"fk-dashboard-layout__content\">\n <!--\n A panel beside the page \u2014 a secondary navigation, a filter rail \u2014 sits in\n the content row ahead of the scroll container, so the topbar and the page\n scroll under it rather than it scrolling with them.\n -->\n <ng-content select=\"[layoutContentPanel]\" />\n\n <!--\n The scroll container. The topbar sticks at its top and the page scrolls\n under it, which is what lets the frosted bar show content through.\n -->\n <div class=\"fk-dashboard-layout__body\">\n <header class=\"fk-dashboard-layout__topbar\">\n <div class=\"fk-dashboard-layout__topbar-inner\">\n <button\n type=\"button\"\n class=\"fk-dashboard-layout__menu\"\n [attr.aria-label]=\"menuAriaLabel()\"\n (click)=\"openSidenav()\"\n >\n <ng-content select=\"[layoutMenuIcon]\" />\n </button>\n\n <div class=\"fk-dashboard-layout__topbar-start\">\n <ng-content select=\"[layoutTopbarStart]\" />\n </div>\n\n <div class=\"fk-dashboard-layout__topbar-end\">\n <ng-content select=\"[layoutTopbarEnd]\" />\n </div>\n </div>\n </header>\n\n <div class=\"fk-dashboard-layout__page\">\n <ng-content />\n\n @if (pageLoading()) {\n <div class=\"fk-dashboard-layout__page-loader\" aria-live=\"polite\">\n <ng-content select=\"[layoutPageLoader]\" />\n </div>\n }\n </div>\n </div>\n </div>\n\n <!--\n A plain div, not a second `aside`: `fk-app-shell` already makes its end\n region an aside, and nesting one inside it would declare two landmarks for\n one panel.\n -->\n <div appShellEnd class=\"fk-dashboard-layout__end\">\n <ng-content select=\"[layoutEnd]\" />\n </div>\n\n <footer appShellFooter class=\"fk-dashboard-layout__footer\">\n <ng-content select=\"[layoutFooter]\" />\n </footer>\n</fk-app-shell>\n", styles: [":host{display:flex;flex-direction:column;height:var(--fk-dashboard-layout-height, 100vh);overflow:hidden;--_max-width: var(--fk-dashboard-layout-max-width, 1400px);--_topbar-height: var(--fk-dashboard-layout-topbar-height, 4rem)}fk-app-shell{flex:1;min-height:0}.fk-dashboard-layout__aside{display:flex;flex-direction:column;height:100%;background:var(--fk-dashboard-layout-aside-bg, var(--fk-color-surface, #ffffff));border-right:1px solid var(--fk-dashboard-layout-aside-border-color, var(--fk-color-border, #d9e2ee))}.fk-dashboard-layout__aside-header{display:flex;align-items:center;gap:var(--fk-rhythm-2, .5rem);flex-shrink:0;padding:var(--fk-dashboard-layout-aside-header-padding, var(--fk-rhythm-4, 1rem) var(--fk-rhythm-5, 1.25rem))}.fk-dashboard-layout__brand{flex:1 1 auto;min-width:0;display:flex;align-items:center}.fk-dashboard-layout__aside-body{flex:1;min-height:0;overflow-y:auto}.fk-dashboard-layout__aside-footer{flex-shrink:0}.fk-dashboard-layout__aside-footer:empty{display:none}.fk-dashboard-layout__toggle,.fk-dashboard-layout__menu{display:grid;place-items:center;flex:none;padding:0;border:1px solid transparent;border-radius:var(--fk-radius-sm, .25rem);background:none;color:var(--fk-dashboard-layout-toggle-color, var(--fk-color-muted, #8a98a8));cursor:pointer;transition:border-color .15s,background-color .15s,color .15s}.fk-dashboard-layout__toggle:hover,.fk-dashboard-layout__menu:hover{border-color:var(--fk-dashboard-layout-toggle-hover-border-color, var(--fk-color-border, #d9e2ee));background:var(--fk-dashboard-layout-toggle-hover-bg, var(--fk-color-surface, #ffffff));color:var(--fk-dashboard-layout-toggle-hover-color, var(--fk-color-text, #1f2d3d))}.fk-dashboard-layout__toggle:focus-visible,.fk-dashboard-layout__menu:focus-visible{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-dashboard-layout__toggle:not(:has(*)):before,.fk-dashboard-layout__menu:not(:has(*)):before{content:\"\";width:1rem;height:.75rem;background:linear-gradient(currentColor 0 2px,transparent 2px 5px,currentColor 5px 7px,transparent 7px 10px,currentColor 10px 12px)}.fk-dashboard-layout__toggle{width:var(--fk-dashboard-layout-toggle-size, 2rem);height:var(--fk-dashboard-layout-toggle-size, 2rem)}.fk-dashboard-layout__menu{width:var(--fk-dashboard-layout-menu-size, 2.25rem);height:var(--fk-dashboard-layout-menu-size, 2.25rem)}.fk-dashboard-layout__content{display:flex;flex-direction:column;height:100%;min-height:0}.fk-dashboard-layout__content:has(>:not(.fk-dashboard-layout__body)){flex-direction:row;width:100%}.fk-dashboard-layout__body{flex:1;min-width:0;min-height:0;overflow-y:auto;overscroll-behavior:contain}.fk-dashboard-layout__topbar{position:sticky;top:0;z-index:20;height:var(--_topbar-height);background:var(--fk-dashboard-layout-topbar-bg, rgba(251, 251, 253, .82));backdrop-filter:blur(var(--fk-dashboard-layout-topbar-blur, 14px));-webkit-backdrop-filter:blur(var(--fk-dashboard-layout-topbar-blur, 14px));border-bottom:1px solid var(--fk-dashboard-layout-topbar-border-color, var(--fk-color-border, #d9e2ee))}.fk-dashboard-layout__topbar-inner{display:flex;align-items:center;gap:var(--fk-rhythm-4, 1rem);height:100%;max-width:var(--_max-width);margin-inline:auto;padding-inline:var(--fk-dashboard-layout-topbar-padding-inline, var(--fk-rhythm-8, 2rem))}.fk-dashboard-layout__topbar-start{display:flex;align-items:center;min-width:0}.fk-dashboard-layout__topbar-end{display:flex;align-items:center;gap:var(--fk-rhythm-3, .75rem);margin-left:auto}.fk-dashboard-layout__menu{display:none}.fk-dashboard-layout__end{display:flex;flex-direction:column;height:100%;min-height:0}.fk-dashboard-layout__end:empty{display:none}.fk-dashboard-layout__page{container-type:inline-size;position:relative;max-width:var(--_max-width);margin-inline:auto;padding:var(--fk-dashboard-layout-page-padding, var(--fk-rhythm-4, 1rem));min-height:calc(100% - var(--_topbar-height))}.fk-dashboard-layout__page-loader{position:absolute;inset:0;z-index:10;display:flex;align-items:center;justify-content:center;min-height:12rem;background:var(--fk-dashboard-layout-page-loader-bg, color-mix(in srgb, var(--fk-color-bg, #fbfbfd) 72%, transparent));backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fk-dashboard-layout__footer{position:relative;z-index:100;display:flex;align-items:center;justify-content:center;flex-shrink:0;height:var(--fk-dashboard-layout-footer-height, 2.5rem);background:var(--fk-dashboard-layout-footer-bg, var(--fk-color-surface, #ffffff));border-top:1px solid var(--fk-dashboard-layout-footer-border-color, var(--fk-color-border, #d9e2ee));font-family:var(--fk-dashboard-layout-footer-font-family, var(--fk-font-family-base, sans-serif));font-size:var(--fk-dashboard-layout-footer-font-size, var(--fk-typography-small-font-size, .75rem));color:var(--fk-dashboard-layout-footer-color, var(--fk-color-muted, #8a98a8))}.fk-dashboard-layout__footer:empty{display:none}:host(.fk-dashboard-layout--collapsed) .fk-dashboard-layout__aside-header{justify-content:center;padding-inline:0}:host(.fk-dashboard-layout--collapsed) .fk-dashboard-layout__brand{display:none}@media(min-width:48em){.fk-dashboard-layout__page{padding:var(--fk-dashboard-layout-page-padding-wide, var(--fk-rhythm-6, 1.5rem) var(--fk-rhythm-8, 2rem))}}@media(max-width:760px){.fk-dashboard-layout__menu{display:grid}.fk-dashboard-layout__topbar-inner{padding-inline:var(--fk-rhythm-4, 1rem)}}@media(prefers-reduced-motion:reduce){.fk-dashboard-layout__toggle,.fk-dashboard-layout__menu{transition:none}}\n"], dependencies: [{ kind: "component", type: AppShellComponent, selector: "fk-app-shell", inputs: ["mode", "sidenavWidth", "collapsedWidth", "breakpoint", "sticky", "collapseOnMobile", "endMode", "endWidth", "endCollapsedWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2442
|
-
}
|
|
2443
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DashboardLayoutComponent, decorators: [{
|
|
2444
|
-
type: Component,
|
|
2445
|
-
args: [{ selector: 'fk-dashboard-layout', standalone: true, imports: [AppShellComponent], encapsulation: ViewEncapsulation.Emulated, changeDetection: ChangeDetectionStrategy.OnPush, template: "<!--\n Banners sit above the shell, in flow, inside the fixed-height host: the\n shell absorbs whatever height they leave, so a banner appearing never adds a\n document scrollbar.\n-->\n<ng-content select=\"[layoutBanner]\" />\n\n<fk-app-shell\n [mode]=\"mode()\"\n [sidenavWidth]=\"sidenavWidth()\"\n [collapsedWidth]=\"collapsedWidth()\"\n [endMode]=\"endMode()\"\n [endWidth]=\"endWidth()\"\n [endCollapsedWidth]=\"endCollapsedWidth()\"\n>\n <div appShellSidenav class=\"fk-dashboard-layout__aside\">\n <div class=\"fk-dashboard-layout__aside-header\">\n <div class=\"fk-dashboard-layout__brand\">\n <ng-content select=\"[layoutBrand]\" />\n </div>\n\n <button\n type=\"button\"\n class=\"fk-dashboard-layout__toggle\"\n [attr.aria-label]=\"toggleAriaLabel()\"\n [attr.aria-expanded]=\"!collapsed()\"\n (click)=\"toggleSidenav()\"\n >\n <ng-content select=\"[layoutToggleIcon]\" />\n </button>\n </div>\n\n <div class=\"fk-dashboard-layout__aside-body\">\n <ng-content select=\"[layoutAside]\" />\n </div>\n\n <div class=\"fk-dashboard-layout__aside-footer\">\n <ng-content select=\"[layoutAsideFooter]\" />\n </div>\n </div>\n\n <div appShellContent class=\"fk-dashboard-layout__content\">\n <!--\n A panel beside the page \u2014 a secondary navigation, a filter rail \u2014 sits in\n the content row ahead of the scroll container, so the topbar and the page\n scroll under it rather than it scrolling with them.\n -->\n <ng-content select=\"[layoutContentPanel]\" />\n\n <!--\n The scroll container. The topbar sticks at its top and the page scrolls\n under it, which is what lets the frosted bar show content through.\n -->\n <div class=\"fk-dashboard-layout__body\">\n <header class=\"fk-dashboard-layout__topbar\">\n <div class=\"fk-dashboard-layout__topbar-inner\">\n <button\n type=\"button\"\n class=\"fk-dashboard-layout__menu\"\n [attr.aria-label]=\"menuAriaLabel()\"\n (click)=\"openSidenav()\"\n >\n <ng-content select=\"[layoutMenuIcon]\" />\n </button>\n\n <div class=\"fk-dashboard-layout__topbar-start\">\n <ng-content select=\"[layoutTopbarStart]\" />\n </div>\n\n <div class=\"fk-dashboard-layout__topbar-end\">\n <ng-content select=\"[layoutTopbarEnd]\" />\n </div>\n </div>\n </header>\n\n <div class=\"fk-dashboard-layout__page\">\n <ng-content />\n\n @if (pageLoading()) {\n <div class=\"fk-dashboard-layout__page-loader\" aria-live=\"polite\">\n <ng-content select=\"[layoutPageLoader]\" />\n </div>\n }\n </div>\n </div>\n </div>\n\n <!--\n A plain div, not a second `aside`: `fk-app-shell` already makes its end\n region an aside, and nesting one inside it would declare two landmarks for\n one panel.\n -->\n <div appShellEnd class=\"fk-dashboard-layout__end\">\n <ng-content select=\"[layoutEnd]\" />\n </div>\n\n <footer appShellFooter class=\"fk-dashboard-layout__footer\">\n <ng-content select=\"[layoutFooter]\" />\n </footer>\n</fk-app-shell>\n", styles: [":host{display:flex;flex-direction:column;height:var(--fk-dashboard-layout-height, 100vh);overflow:hidden;--_max-width: var(--fk-dashboard-layout-max-width, 1400px);--_topbar-height: var(--fk-dashboard-layout-topbar-height, 4rem)}fk-app-shell{flex:1;min-height:0}.fk-dashboard-layout__aside{display:flex;flex-direction:column;height:100%;background:var(--fk-dashboard-layout-aside-bg, var(--fk-color-surface, #ffffff));border-right:1px solid var(--fk-dashboard-layout-aside-border-color, var(--fk-color-border, #d9e2ee))}.fk-dashboard-layout__aside-header{display:flex;align-items:center;gap:var(--fk-rhythm-2, .5rem);flex-shrink:0;padding:var(--fk-dashboard-layout-aside-header-padding, var(--fk-rhythm-4, 1rem) var(--fk-rhythm-5, 1.25rem))}.fk-dashboard-layout__brand{flex:1 1 auto;min-width:0;display:flex;align-items:center}.fk-dashboard-layout__aside-body{flex:1;min-height:0;overflow-y:auto}.fk-dashboard-layout__aside-footer{flex-shrink:0}.fk-dashboard-layout__aside-footer:empty{display:none}.fk-dashboard-layout__toggle,.fk-dashboard-layout__menu{display:grid;place-items:center;flex:none;padding:0;border:1px solid transparent;border-radius:var(--fk-radius-sm, .25rem);background:none;color:var(--fk-dashboard-layout-toggle-color, var(--fk-color-muted, #8a98a8));cursor:pointer;transition:border-color .15s,background-color .15s,color .15s}.fk-dashboard-layout__toggle:hover,.fk-dashboard-layout__menu:hover{border-color:var(--fk-dashboard-layout-toggle-hover-border-color, var(--fk-color-border, #d9e2ee));background:var(--fk-dashboard-layout-toggle-hover-bg, var(--fk-color-surface, #ffffff));color:var(--fk-dashboard-layout-toggle-hover-color, var(--fk-color-text, #1f2d3d))}.fk-dashboard-layout__toggle:focus-visible,.fk-dashboard-layout__menu:focus-visible{outline:none;box-shadow:var(--fk-focus-ring, 0 0 0 3px rgba(10, 132, 255, .18))}.fk-dashboard-layout__toggle:not(:has(*)):before,.fk-dashboard-layout__menu:not(:has(*)):before{content:\"\";width:1rem;height:.75rem;background:linear-gradient(currentColor 0 2px,transparent 2px 5px,currentColor 5px 7px,transparent 7px 10px,currentColor 10px 12px)}.fk-dashboard-layout__toggle{width:var(--fk-dashboard-layout-toggle-size, 2rem);height:var(--fk-dashboard-layout-toggle-size, 2rem)}.fk-dashboard-layout__menu{width:var(--fk-dashboard-layout-menu-size, 2.25rem);height:var(--fk-dashboard-layout-menu-size, 2.25rem)}.fk-dashboard-layout__content{display:flex;flex-direction:column;height:100%;min-height:0}.fk-dashboard-layout__content:has(>:not(.fk-dashboard-layout__body)){flex-direction:row;width:100%}.fk-dashboard-layout__body{flex:1;min-width:0;min-height:0;overflow-y:auto;overscroll-behavior:contain}.fk-dashboard-layout__topbar{position:sticky;top:0;z-index:20;height:var(--_topbar-height);background:var(--fk-dashboard-layout-topbar-bg, rgba(251, 251, 253, .82));backdrop-filter:blur(var(--fk-dashboard-layout-topbar-blur, 14px));-webkit-backdrop-filter:blur(var(--fk-dashboard-layout-topbar-blur, 14px));border-bottom:1px solid var(--fk-dashboard-layout-topbar-border-color, var(--fk-color-border, #d9e2ee))}.fk-dashboard-layout__topbar-inner{display:flex;align-items:center;gap:var(--fk-rhythm-4, 1rem);height:100%;max-width:var(--_max-width);margin-inline:auto;padding-inline:var(--fk-dashboard-layout-topbar-padding-inline, var(--fk-rhythm-8, 2rem))}.fk-dashboard-layout__topbar-start{display:flex;align-items:center;min-width:0}.fk-dashboard-layout__topbar-end{display:flex;align-items:center;gap:var(--fk-rhythm-3, .75rem);margin-left:auto}.fk-dashboard-layout__menu{display:none}.fk-dashboard-layout__end{display:flex;flex-direction:column;height:100%;min-height:0}.fk-dashboard-layout__end:empty{display:none}.fk-dashboard-layout__page{container-type:inline-size;position:relative;max-width:var(--_max-width);margin-inline:auto;padding:var(--fk-dashboard-layout-page-padding, var(--fk-rhythm-4, 1rem));min-height:calc(100% - var(--_topbar-height))}.fk-dashboard-layout__page-loader{position:absolute;inset:0;z-index:10;display:flex;align-items:center;justify-content:center;min-height:12rem;background:var(--fk-dashboard-layout-page-loader-bg, color-mix(in srgb, var(--fk-color-bg, #fbfbfd) 72%, transparent));backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}.fk-dashboard-layout__footer{position:relative;z-index:100;display:flex;align-items:center;justify-content:center;flex-shrink:0;height:var(--fk-dashboard-layout-footer-height, 2.5rem);background:var(--fk-dashboard-layout-footer-bg, var(--fk-color-surface, #ffffff));border-top:1px solid var(--fk-dashboard-layout-footer-border-color, var(--fk-color-border, #d9e2ee));font-family:var(--fk-dashboard-layout-footer-font-family, var(--fk-font-family-base, sans-serif));font-size:var(--fk-dashboard-layout-footer-font-size, var(--fk-typography-small-font-size, .75rem));color:var(--fk-dashboard-layout-footer-color, var(--fk-color-muted, #8a98a8))}.fk-dashboard-layout__footer:empty{display:none}:host(.fk-dashboard-layout--collapsed) .fk-dashboard-layout__aside-header{justify-content:center;padding-inline:0}:host(.fk-dashboard-layout--collapsed) .fk-dashboard-layout__brand{display:none}@media(min-width:48em){.fk-dashboard-layout__page{padding:var(--fk-dashboard-layout-page-padding-wide, var(--fk-rhythm-6, 1.5rem) var(--fk-rhythm-8, 2rem))}}@media(max-width:760px){.fk-dashboard-layout__menu{display:grid}.fk-dashboard-layout__topbar-inner{padding-inline:var(--fk-rhythm-4, 1rem)}}@media(prefers-reduced-motion:reduce){.fk-dashboard-layout__toggle,.fk-dashboard-layout__menu{transition:none}}\n"] }]
|
|
2446
|
-
}], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], sidenavWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidenavWidth", required: false }] }], collapsedWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsedWidth", required: false }] }], endMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "endMode", required: false }] }], endWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "endWidth", required: false }] }], endCollapsedWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "endCollapsedWidth", required: false }] }], pageLoading: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageLoading", required: false }] }], toggleAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "toggleAriaLabel", required: false }] }], menuAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuAriaLabel", required: false }] }], className: [{ type: i0.Input, args: [{ isSignal: true, alias: "className", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], shell: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AppShellComponent), { isSignal: true }] }], hostClass: [{
|
|
2447
|
-
type: HostBinding,
|
|
2448
|
-
args: ['class']
|
|
2449
|
-
}], hostId: [{
|
|
2450
|
-
type: HostBinding,
|
|
2451
|
-
args: ['attr.id']
|
|
2452
|
-
}] } });
|
|
2453
|
-
|
|
2454
2464
|
/**
|
|
2455
2465
|
* A whole dashboard shell in one element: the collapsing aside and its
|
|
2456
2466
|
* toggle, the brand block at its head, the icon-rail navigation, and the
|