import { NgTemplateOutlet } from '@angular/common';
import {
booleanAttribute,
ChangeDetectionStrategy,
Component,
computed,
effect,
inject,
input,
model,
signal,
} from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import {
type IsActiveMatchOptions,
NavigationEnd,
Router,
RouterLink,
} from '@angular/router';
import { filter, map, startWith } from 'rxjs';
import { AfricaniesIconComponent } from '@africanies/africanies-icons';
import { ModeColorService } from '@africanies/africanies-theme';
import { AFRICANIES_BRAND_LOGO_MINI_URL, AFRICANIES_BRAND_LOGO_URL } from '../../brand';
import { resolveActiveSideNavItem } from '../header-back.util';
import { navItemUrlTree } from '../nav-router.util';
import type { AfricaniesSideNavItem } from './side-nav-item';
const DEFAULT_LINK_ACTIVE: IsActiveMatchOptions = {
paths: 'subset',
queryParams: 'subset',
fragment: 'ignored',
matrixParams: 'ignored',
};
/**
* App shell side navigation with icons, nested items, and a collapsible rail.
*
* **Design - ink spine:** a continuous mode-accent edge; active leaves use
* primary fill + white text (portal parity); expanded parents of an active
* child use primary text on white. Collapsed mode keeps icons; hover opens a
* floating label blade (name + children) instead of a plain tooltip.
*
* ## Parent items with children
* **Expanded rail:** branches start open by default (`expandBranchesByDefault`).
* Clicking a parent only opens/closes the branch (no route change). When any
* branch is open, a sticky collapse-all control sits above the list (top right).
* The rail expand/collapse control stays pinned in the logo header. Project
* chrome above the scrollable list with `pre-nav` (e.g. shipping modes) or
* below with `footer`.
* **Collapsed rail:** clicking a parent expands the rail, opens the
* branch, and activates the first enabled child (router or `activeId`).
*
* ## Router mode
* Set `routerLink` on items. Active state follows the consumer's Router
* (including cold loads).
*
* ## Local mode
* Omit `routerLink` and bind `[(activeId)]`.
*
* @example
* ```html
*
* ```
*/
@Component({
selector: 'africanies-side-nav',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [AfricaniesIconComponent, RouterLink, NgTemplateOutlet],
host: {
class: 'relative z-20 block h-full min-h-0',
},
styleUrl: './africanies-side-nav.component.css',
templateUrl: './africanies-side-nav.component.html',
})
/**
* App shell side navigation with icons, nested items, and a collapsible rail.
*/
export class SideNavComponent {
protected readonly modeColor = inject(ModeColorService);
private readonly defaultLogoUrl = inject(AFRICANIES_BRAND_LOGO_URL);
private readonly defaultLogoMiniUrl = inject(AFRICANIES_BRAND_LOGO_MINI_URL);
private readonly router = inject(Router);
/** Navigation tree. */
readonly items = input.required();
/** When true, the rail collapses to icons only. Two-way bindable. */
readonly collapsed = model(false);
/**
* Active item id for local (non-routed) trees. Synced from the router when
* items use `routerLink`.
*/
readonly activeId = model(null);
/** Accessible label for the `