import { LitElement, type PropertyValueMap } from 'lit'; import './headerCategory'; import '../../reusable/button/button'; import './headerLink'; declare const _defaultTextStrings: { back: string; more: string; }; type HeaderTextStrings = typeof _defaultTextStrings; export interface HeaderCategoryLinkType { id: string; label: string; href?: string; target?: '_blank' | '_self' | '_parent' | '_top'; rel?: string; } export interface HeaderCategoryType { id: string; heading: string; links: HeaderCategoryLinkType[]; } export interface HeaderLinkRendererContext { tabId: string; categoryId: string; view: 'root' | 'detail'; } export type HeaderMegaLinkRenderer = (link: HeaderCategoryLinkType, context?: HeaderLinkRendererContext) => string | null; export interface MegaTabConfig { categories: HeaderCategoryType[]; } export interface MegaTabsConfig { [tabId: string]: MegaTabConfig; } export interface HeaderMegaChangeDetail { activeMegaTabId: string; activeMegaCategoryId: string | null; view: HeaderView; } type HeaderView = 'root' | 'detail'; interface SlottedLinkData { href: string; inner: string; textContent: string; target?: string; rel?: string; } interface SlottedCategoryData { id: string; heading: string; links: SlottedLinkData[]; iconHtml?: string; showDivider: boolean; noAutoDivider: boolean; } /** * Header categories wrapper for mega menu. * * @slot unnamed - Slot for header category elements. * * Controlled via `activeMegaTabId` / `activeMegaCategoryId` but encapsulates * all categorical/mega-nav view behavior (root/detail, "More", "Back"). * * Emits `on-nav-change` so parents can mirror state for tabs, routing, etc. * * Modes: * - JSON mode * - Provide `tabsConfig` and categories/links are rendered from config. * - Each link may specify `href`, `target`, and `rel`. * - Optional `linkRenderer` hook can be supplied to fully control the * slotted content inside each ``. * * - Slotted/manual mode * - Omit `tabsConfig` and slot `` / `` * elements directly in the light DOM. * - Slotted `` `href`, `target`, and `rel` attributes are * preserved. * - Root view will: * - limit visible links per category at `maxRootLinks` * - inject a "More" link when there are additional links * - "More" switches to a detail view for that category, and the Back button * returns to the root view. * * @fires on-nav-change - Fires when the active category/tab view changes. Detail: `{ activeMegaTabId, activeMegaCategoryId, view }`. * @cssprop [--kyn-header-category-column-width=300px] - Width of each column. Applies to 1 and 2 column layouts. Also used for 3+ when `fixed-column-widths` is enabled. * @cssprop [--kyn-header-category-column-gap=32px] - Horizontal gap between columns. */ export declare class HeaderCategories extends LitElement { static styles: import("lit").CSSResult; /** Configuration object for the mega nav (tab id -> categories/links). */ accessor tabsConfig: MegaTabsConfig | null; /** Currently active tab id. */ accessor activeMegaTabId: string; /** Currently active category id in detail view, or null for root view (controlled). */ accessor activeMegaCategoryId: string | null; /** Max number of links to render in root columns before showing "More". */ accessor maxRootLinks: number; /** Controls whether root-view categories are limited by `maxRootLinks` before showing "More". */ accessor limitRootLinks: boolean; /** * Layout mode for categories. * - "" (default): Legacy responsive column-width layout for standard mega-nav * - "masonry": CSS multi-column with fixed column-count based on category count * - "grid": CSS Grid with fixed columns and row-based wrapping */ accessor layout: 'masonry' | 'grid' | ''; /** Max number of columns to display when layout="grid" or layout="masonry". */ accessor maxColumns: number; /** * When true, 3+ columns use fixed column widths instead of stretching to fill * the full flyout width. The flyout remains constrained by viewport max-width. */ accessor fixedColumnWidths: boolean; /** When true, category headings render with the default design-system icon when none is provided. */ accessor showCategoryIcons: boolean; /** When true, hide dividers in root-view categories. */ accessor hideCategoryDividers: boolean; /** * Optional text overrides, merged with defaults. * e.g. */ accessor textStrings: Partial | null; /** Resolved text strings (defaults + overrides). * @internal */ accessor _textStrings: HeaderTextStrings; /** Number of links per column in the detail view (JSON mode only). */ accessor detailLinksPerColumn: number; /** * Current visual view for styling ('root' | 'detail'). * Derived from `activeMegaCategoryId` but reflected for CSS hooks. * @internal */ accessor view: HeaderView; /** * Optional hook to render the entire link content slotted into . * * IMPORTANT: * - This must return an HTML string or null. * - The string is rendered via unsafeHTML; consumers are responsible for sanitizing * any dynamic content they inject here. * * This API is intentionally framework-agnostic: React, Vue, Angular, etc. can all * build a string and pass it in. * * If not provided, a simple circle-icon + label placeholder is used. */ accessor linkRenderer: HeaderMegaLinkRenderer | null; /** Internal representation of slotted categories * @internal */ accessor _slottedCategories: SlottedCategoryData[]; /** @internal */ private _buildSlottedRaf?; /** @internal */ private _resizeObserver?; /** Owning nav used for scoped on-nav-toggle subscription. * @internal */ private _owningNav; /** Debounced divider update to prevent jank during rapid resize (grid and masonry modes) * @internal */ private _debouncedUpdateDividers; /** Tracks the last emitted column count to avoid duplicate events * @internal */ private _lastEmittedColumnCount; /** Wrapper for ResizeObserver callback * @internal */ private _handleResize; /** * Update category count and emit event if changed. * Emits for grid and masonry layouts so the parent flyout can adjust width. * @internal */ private _updateAndEmitColumnCount; /** @internal */ private readonly _boundHandleNavToggle; /** Find the closest owning header nav across shadow boundaries. * @internal */ private _resolveOwningNav; /** @internal */ private get _isJsonMode(); /** @internal */ private get _tabConfig(); private chunkBy; private normalizeHeaderLinkTarget; /** Resolve max root links. Disabling limiting, or using non-positive values, means "no limit". */ private get _rootLinksLimit(); private _emitChange; setRootView(tabId?: string): void; openCategoryDetail(tabId: string, categoryId: string, e?: Event): void; handleBackClick(e?: Event): void; private _handleNavToggle; willUpdate(changed: PropertyValueMap): void; updated(changed: PropertyValueMap): void; private renderLinkContent; private renderCategoryColumn; private renderRootView; private renderDetailView; private _buildSlottedCategories; private renderSlottedRoot; private computeDetailColumns; private renderSlottedDetail; private _scheduleBuildSlottedCategories; /** * After render, detect which categories are in the last visual row * and disable their dividers. CSS Grid determines row breaks dynamically, * so we must inspect rendered positions. * @internal */ private _updateDividers; /** * Get the number of columns to display (grid and masonry modes). * Returns the minimum of category count and maxColumns. * @internal */ private _getColumnCount; render(): import("lit-html").TemplateResult<1>; connectedCallback(): void; disconnectedCallback(): void; } declare global { interface HTMLElementTagNameMap { 'kyn-header-categories': HeaderCategories; } } export {}; //# sourceMappingURL=headerCategories.d.ts.map