UNPKG

@dvcol/neo-svelte

Version:

Neomorphic ui library for svelte 5

164 lines (163 loc) 5.47 kB
import type { Snippet } from 'svelte'; import type { NeoButtonProps } from '../../buttons/neo-button.model.js'; import type { NeoDividerProps } from '../../divider/neo-divider.model.js'; import type { NeoMenuListProps } from './neo-menu-list.model.js'; import type { NeoTooltipProps } from '../tooltips/neo-tooltip.model.js'; import type { NeoListBaseItemProps } from '../../list/neo-list-base-item.model.js'; import type { NeoBaseListItem } from '../../list/neo-list.model.js'; import type { BorderRadiusInput } from '../../utils/border.utils.js'; import type { HTMLNeoBaseElement, SvelteEvent } from '../../utils/html-element.utils.js'; export interface NeoMenuItem<Value = unknown, Tag extends keyof HTMLElementTagNameMap = 'li'> extends Omit<NeoBaseListItem<Value, Tag, NeoMenuContext<Value, Tag>>, 'containerProps'>, Pick<NeoMenuListItemProps, 'tooltipProps' | 'baseProps'> { /** * If true, children items will be rendered as list items instead of a nested dropdown menu. * * @default false */ section?: boolean; /** * If true, the menu section label will be sticky on scroll. */ sticky?: boolean; /** * If true, the menu will stay open when the item is selected. */ keepOpenOnSelect?: boolean; /** * The nested menu items. */ items?: NeoMenuItem<Value, Tag>[]; /** * Optional menu props to pass to the menu list wrapper. */ menuProps?: Omit<NeoMenuListProps<Value>, 'itemProps' | 'baseProps' | 'tooltipProps' | 'items' | 'item' | 'ref'>; /** * Optional props to pass to the base list item. */ itemProps?: Pick<NeoBaseListItem<Value, Tag, NeoMenuContext<Value, Tag>>, 'containerProps'>; } export interface NeoMenuContext<Value = unknown, Tag extends keyof HTMLElementTagNameMap = 'li'> { /** * The item itself. */ item: NeoMenuItem<Value, Tag>; /** * The parent item (if any). */ parent?: NeoMenuItem<Value, Tag>; /** * The array of items this item belongs to. */ array?: NeoMenuItem<Value, Tag>[]; /** * The index of the item in the menu. */ index: number; /** * The index of the parent section in the menu (if any). */ sectionIndex?: number; /** * The nested level of the menu. * * @default 1 */ level?: number; /** * Whether the item nested menu is open (if any). */ open?: boolean; /** * If true, the menu will stay open when the item is selected. */ keepOpenOnSelect?: boolean; /** * Event handler for when a menu item with a nested menu is clicked. * @param item - The menu item that was clicked. * @param e - The pointer event. */ onMenu: (item: NeoMenuItem<Value>, e: SvelteEvent<MouseEvent>) => void; /** * Event handler for when a menu item without a nested menu is clicked. * @param item - The menu item that was clicked. * @param e - The pointer event. */ onSelect: (item: NeoMenuItem<Value>, e: SvelteEvent<MouseEvent>) => void; } export type NeoMenuListItemProps<Value = unknown, Tag extends keyof HTMLElementTagNameMap = 'li'> = { /** * The content of the list item. * If none is provided, the default content will be used. */ children?: Snippet<[NeoMenuContext<Value, Tag>]>; /** * The reference to the list item element. */ ref?: HTMLElement; /** * The tag name of the list item element. * * @default 'li' */ tag?: Tag; /** * The tag name of the menu element. * * @default 'ul' */ menuTag?: keyof HTMLElementTagNameMap; /** * The reference to the tooltip element. */ tooltipRef?: NeoTooltipProps['ref']; /** * The default tooltip placement. * * @default 'right-start' */ placement?: NeoTooltipProps['placement']; /** * An optional offset for the tooltip. */ offset?: NeoTooltipProps['offset']; /** * If true, the menu & items will be rounded. */ rounded?: BorderRadiusInput; /** * Reverse the direction of the item. * * @default false */ reverse?: boolean; /** * Whether to display a divider above items in the list. * If an item divider option is set, it will take precedence over the list divider. * * @default false */ divider?: boolean; /** * Reverse the next/previous focusable sibling selection direction using arrow keys. */ flip?: boolean; /** * Optional props to pass to the divider (if any. */ dividerProps?: Partial<NeoDividerProps>; /** * Optional props to pass to the tooltip (if any). */ tooltipProps?: Partial<Omit<NeoTooltipProps, 'ref' | 'children' | 'tooltip'>>; /** * Optional props to pass to the base list item. */ baseProps?: Partial<NeoListBaseItemProps<Value, NeoMenuContext<Value, Tag>>>; /** * Optional props to pass to the menu list. */ menuProps?: Omit<NeoMenuListProps<Value>, 'items' | 'item' | 'ref' | 'onMenu' | 'onSelect'>; /** * Optional props to pass to the button. */ buttonProps?: NeoButtonProps; } & Pick<NeoMenuContext<Value, Tag>, 'item' | 'parent' | 'array' | 'index' | 'sectionIndex' | 'level' | 'parent' | 'open' | 'keepOpenOnSelect' | 'onMenu' | 'onSelect'> & Omit<HTMLNeoBaseElement<HTMLElementTagNameMap[Tag]>, 'children'>;