@dvcol/neo-svelte
Version:
Neomorphic ui library for svelte 5
164 lines (163 loc) • 5.47 kB
TypeScript
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'>;