/** * NavTree — 3-level recursive sidebar nav primitive. * * Generic and prop-driven: no `$app/*` imports, no SvelteKit dependency. * Consumers pass `currentPath` (e.g. from `page.url.pathname`) and an * optional `iconComponent` for rendering `NavItem.icon` names. When no * icon component is supplied, the raw `icon` string is rendered as text * (useful for emoji / symbol icons). * * Active-state logic is overridable via `isActive`; the default treats * `currentPath === item.href` or `currentPath.startsWith(item.href + '/')` * as active (unless `item.exact === true`). * * In `collapsed` mode the component renders icon-only chips with a * native `title` tooltip; child rows are hidden unless their parent is * itself active (so the chip can highlight without expanding). */ import type { Component } from 'svelte'; import type { NavItem } from './types.js'; interface Props { /** Top-level nav items. Each may have up to two levels of children. */ items: NavItem[]; /** Current pathname. Required — consumers pass `page.url.pathname` or similar. */ currentPath: string; /** Called on link click. Consumers typically close a mobile drawer here. */ onNavigate?: () => void; /** Override active-detection. Defaults to `defaultIsActive`. */ isActive?: (item: NavItem, currentPath: string) => boolean; /** * Optional icon renderer. If omitted, `item.icon` is rendered as plain * text inside the icon slot — handy for emoji/symbol icons. */ iconComponent?: Component<{ name: string; size?: number; }>; /** Render in collapsed (icon-only) mode. */ collapsed?: boolean; /** Accessible label for the surrounding `