mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-30 14:41:16 +00:00
119 lines
2.3 KiB
TypeScript
119 lines
2.3 KiB
TypeScript
'use client';
|
|
import type { ComponentProps, ReactNode } from 'react';
|
|
import { usePathname } from '@hanzo/docs-core/framework';
|
|
import { isActive } from './urls';
|
|
import Link from '@hanzo/docs-core/link';
|
|
|
|
interface Filterable {
|
|
/**
|
|
* Restrict where the item is displayed
|
|
*
|
|
* @defaultValue 'all'
|
|
*/
|
|
on?: 'menu' | 'nav' | 'all';
|
|
}
|
|
|
|
interface WithHref {
|
|
url: string;
|
|
/**
|
|
* When the item is marked as active
|
|
*
|
|
* @defaultValue 'url'
|
|
*/
|
|
active?: 'url' | 'nested-url' | 'none';
|
|
external?: boolean;
|
|
}
|
|
|
|
export interface MainItemType extends WithHref, Filterable {
|
|
type?: 'main';
|
|
icon?: ReactNode;
|
|
text: ReactNode;
|
|
description?: ReactNode;
|
|
}
|
|
|
|
export interface IconItemType extends WithHref, Filterable {
|
|
type: 'icon';
|
|
/**
|
|
* `aria-label` of icon button
|
|
*/
|
|
label?: string;
|
|
icon: ReactNode;
|
|
text: ReactNode;
|
|
/**
|
|
* @defaultValue true
|
|
*/
|
|
secondary?: boolean;
|
|
}
|
|
|
|
export interface ButtonItemType extends WithHref, Filterable {
|
|
type: 'button';
|
|
icon?: ReactNode;
|
|
text: ReactNode;
|
|
/**
|
|
* @defaultValue false
|
|
*/
|
|
secondary?: boolean;
|
|
}
|
|
|
|
export interface MenuItemType extends Partial<WithHref>, Filterable {
|
|
type: 'menu';
|
|
icon?: ReactNode;
|
|
text: ReactNode;
|
|
|
|
items: (
|
|
| (MainItemType & {
|
|
/**
|
|
* Options when displayed on navigation menu
|
|
*/
|
|
menu?: ComponentProps<'a'> & {
|
|
banner?: ReactNode;
|
|
};
|
|
})
|
|
| CustomItemType
|
|
)[];
|
|
|
|
/**
|
|
* @defaultValue false
|
|
*/
|
|
secondary?: boolean;
|
|
}
|
|
|
|
export interface CustomItemType extends Filterable {
|
|
type: 'custom';
|
|
/**
|
|
* @defaultValue false
|
|
*/
|
|
secondary?: boolean;
|
|
children: ReactNode;
|
|
}
|
|
|
|
export type LinkItemType =
|
|
| MainItemType
|
|
| IconItemType
|
|
| ButtonItemType
|
|
| MenuItemType
|
|
| CustomItemType;
|
|
|
|
export function LinkItem({
|
|
ref,
|
|
item,
|
|
...props
|
|
}: Omit<ComponentProps<'a'>, 'href'> & { item: LinkItemType & WithHref }) {
|
|
const active = useLinkItemActive(item);
|
|
|
|
return (
|
|
<Link ref={ref} href={item.url} external={item.external} {...props} data-active={active}>
|
|
{props.children}
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
export function useLinkItemActive(link: LinkItemType) {
|
|
const pathname = usePathname();
|
|
|
|
if (link.type === 'custom' || !link.url) return false;
|
|
if (link.active === 'none') return false;
|
|
|
|
return isActive(link.url, pathname, link.active === 'nested-url');
|
|
}
|