import { type ReactNode, type ElementType, type ComponentPropsWithoutRef } from 'react'; export type SubNavigationRenderLabelFunction = (label: string) => ReactNode; export type SubNavigationProps = VerticalSubNavigationProps | HorizontalSubNavigationProps; type VerticalSubNavigationProps = BaseSubNavigationProps & { /** * The list of navigation items. * * - When `orientation` is `"vertical"`, each item **can** have children. */ navigationItems: NavigationItem[]; /** * The orientation for laying out navigation items. * * @default 'vertical' */ orientation?: 'vertical'; }; type HorizontalSubNavigationProps = BaseSubNavigationProps & { /** * The list of navigation items. * * - When `orientation` is `"horizontal"`, each item **cannot** have children. */ navigationItems: ChildlessNavigationItem[]; /** * The orientation for laying out navigation items. * * @default 'vertical' */ orientation?: 'horizontal'; }; /** * Common properties for both vertical and horizontal SubNavigation. */ type BaseSubNavigationProps = { /** * The component to use as the link element instead of the general anchor element ``. * The custom component must extend the HTMLAnchorElement interface. * * If this property is not set, the navigation link is rendered as an general anchor element ``. * * This property depends on the `isExternal` property of each navigation item. * * - If the `isExternal` property is set to true, the navigation link is rendered as an general anchor element `` with `target="_blank"`. * - If the `isExternal` property is set to false, the navigation link is rendered as the custom component. * * Use this property if you want to use a custom component as the navigation link. * e.g. next/link */ customLinkComponent?: ElementType; /** * Custom render function for each navigation item's label. * Receives the item's raw `label` string and returns a ReactNode rendered inside * the default `` wrapper. * When omitted, the label string is rendered directly (default behavior). * * Use this to truncate long labels or otherwise customize how labels are displayed * without losing the built-in semantic markup. * * To show a tooltip on both hover and focus, wrap the entire link with a `Tooltip` * via `customLinkComponent` instead — placing a `Tooltip` inside `renderNavigationLabel` * only works for hover because the tooltip trigger ends up inside the focusable ``, * and focus events do not propagate inward to child elements. * * @param label - The label string of the navigation item. * * @returns ReactNode - Custom content rendered inside the label wrapper. * * @example * ```tsx * // Truncate labels that exceed 2 lines * ( * * {label} * * )} * /> * ``` */ renderNavigationLabel?: SubNavigationRenderLabelFunction; /** * Content displayed above the navigation list, rendered inside a padded wrapper. * Use this to add a feature shortcut, promotional content, or other header-level * UI at the top of the navigation. * * @example * ```tsx * * Upgrade plan * * } * /> * ``` */ headerSlot?: ReactNode; /** * For overriding styles if you need. */ className?: string; }; /** * The union that discriminates whether each navigation item has children. */ type NavigationItem = ChildlessNavigationItem | ParentNavigationItem; /** * The navigation item that has no children. */ type ChildlessNavigationItem = BaseNavigationItem & { /** * No nested navigation items. */ children?: undefined; /** * The path or URL to the linked page. */ href: string; /** * If provided, the item is rendered as a button instead of a link. * The handler is called with the item's `href` value as an argument. * * Use this for state-based navigation patterns where you want to update * application state on click without performing browser navigation. */ onClick?: (href: string) => void; }; /** * The navigation item that has nested children. */ type ParentNavigationItem = BaseNavigationItem & { /** * The nested navigation items. */ children: NavigationItem[]; /** * The path or URL to the linked page. * When this property is set, the parent navigation item would be a link * and only the disclosure icon is a button to expand children. */ href?: string; }; /** * Common properties for all navigation items. */ type BaseNavigationItem = { /** * The text label briefly describing the linked page. */ label: string; /** * Whether the navigation item is the current page. * * If this property is set to true, the navigation item is highlighted as the current page. * When the navigation item is the nested navigation item, the parent navigation is opened by default. */ isCurrent?: boolean; /** * Whether the linked page is external. * * If this property is set to true, `target='_blank' is set to the link`. */ isExternal?: boolean; /** * The icon that is displayed on the left side of the text label. */ labelIcon?: ReactNode; /** * For a status icon or badge that is displayed on the right side of the text label. * If `locked` prop is true, any indicators in this slot will be ignored. */ statusSlot?: ReactNode; /** * Display a lock icon on the right side to indicate the navigation item is locked by permission. * This option does not actually disable the link. */ locked?: boolean; /** * The properties for the lock icon. * * @property aria-label - The alternative text for the lock icon. It's set "ロックされています" by default. */ lockIconProps?: Pick, 'aria-label'>; }; export {};