import type { NeoListBaseItemProps, NeoListBaseSectionProps } from '../index.js';
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 { NeoListBaseLoaderProps } from './neo-list-base-loader.model.js';
import type { HTMAnimationProps, HTMLTransitionProps } from '../utils/action.utils.js';
import type { Color } from '../utils/colors.utils.js';
import type { HTMLNeoBaseElement, HTMLRefProps, HTMLTagProps } from '../utils/html-element.utils.js';
import type { SizeInput } from '../utils/style.utils.js';
export type NeoListDividerOption = {
    top?: boolean;
    bottom?: boolean;
};
export declare const showDivider: (item: NeoListItemOrSection, position?: keyof NeoListDividerOption) => boolean | undefined;
export type NeoListItemCommon<Tag extends keyof HTMLElementTagNameMap = 'li'> = {
    /**
     * Unique identifier for the list item.
     * Used for keying the list item.
     * If not provided, the index will be used.
     * Note: Required for entering/leaving transitions.
     */
    id?: string | number;
    /**
     * The HTML tag to use for the item.
     * @default 'li'
     */
    tag?: Tag;
    /**
     * Text color to use for the item.
     */
    color?: Color | CSSStyleDeclaration['color'];
    /**
     * If true, the list section will display a divider above the title.
     */
    divider?: boolean | NeoListDividerOption;
    /**
     * If true, the item will not be displayed.
     */
    hidden?: boolean;
    /**
     * Optional props to pass to the divider.
     */
    dividerProps?: NeoDividerProps;
    /**
     Optional props to pass to the container.
     */
    containerProps?: HTMLNeoBaseElement<HTMLElementTagNameMap[Tag]>;
};
export type NeoListItemRenderContext<Value = unknown, Tag extends keyof HTMLElementTagNameMap = 'li'> = {
    item: NeoListItem<Value, Tag>;
    index: number;
    checked?: boolean;
    context: NeoListContext;
};
export type NeoListItemRender<Value = unknown, Tag extends keyof HTMLElementTagNameMap = 'li'> = Snippet<[NeoListItemRenderContext<Value, Tag>]>;
export type NeoListItem<Value = unknown, Tag extends keyof HTMLElementTagNameMap = 'li'> = {
    /**
     * An arbitrary value to associate with the list item.
     */
    value: Value;
    /**
     * Optional label to display in the list item.
     * If not provided, the value will be used.
     *
     * @note Recommended in section for accessibility.
     */
    label?: string;
    /**
     * Optional description to display in the list item.
     */
    description?: string;
    /**
     * If true, the list item will be disabled.
     */
    disabled?: boolean;
    /**
     * If true, the item will not trigger selection, but will not be styled as disabled.
     */
    readonly?: boolean;
    /**
     * Optional snippet to display in place of the list item.
     */
    render?: NeoListItemRender<Value, Tag>;
    /**
     * Snippet to display before the list item.
     * e.g. an icon or avatar.
     */
    before?: NeoListItemRender<Value, Tag>;
    /**
     * Snippet to display after the list item.
     * e.g. a badge or action button.
     */
    after?: NeoListItemRender<Value, Tag>;
    /**
     * The url to navigate to when the anchor is clicked.
     */
    href?: NeoButtonProps['href'];
    /**
     * Callback function to be called when the button is clicked.
     */
    onclick?: NeoButtonProps['onclick'];
    /**
     * Optional props to pass to the button.
     */
    buttonProps?: NeoButtonProps;
} & NeoListItemCommon<Tag>;
export type NeoListRenderContext<Value = unknown, Item = NeoListItem | NeoListSection> = {
    items: Item[];
    /**
     * The index of the section in the list.
     */
    index?: number;
    section?: NeoListSection<Value>;
    context?: NeoListContext;
};
export type NeoListRender<Value = unknown> = Snippet<[NeoListRenderContext<Value>]>;
export type NeoListSectionRender<Value = unknown> = Snippet<[NeoListRender<Value>, NeoListRenderContext<Value>]>;
export type NeoListSection<Value = unknown, Tag extends keyof HTMLElementTagNameMap = 'ul'> = {
    /**
     * Array of child list items to display.
     */
    items: NeoListItem<Value>[];
    /**
     * Optional label to display in the list item.
     */
    label: string;
    /**
     * Whether the section is sticky (stays on top while scrolling the content).
     */
    sticky?: boolean;
    /**
     * Optional snippet to display in place of the list section.
     * @param list - The list snippet that render items.
     * @param context - The list section context.
     */
    render?: NeoListSectionRender<Value>;
    /**
     * Optional snippet to display when the section is empty.
     */
    empty?: Snippet<[NeoListContext]>;
    /**
     * Optional props to pass to the section container.
     */
    sectionProps?: HTMLNeoBaseElement<HTMLElementTagNameMap[Tag]>;
} & NeoListItemCommon<Tag>;
export declare const isSection: <Value = unknown>(item: NeoListItem<Value> | NeoListSection<Value>) => item is NeoListSection<Value>;
export type NeoListSelectedItem<Value = unknown, Tag extends keyof HTMLElementTagNameMap = 'li'> = {
    index: number;
    item: NeoListItem<Value, Tag>;
    sectionIndex?: number;
    section?: NeoListSection<Value>;
};
export type NeoListSelectEvent<Selected = NeoListSelectedItem | NeoListSelectedItem[]> = {
    type: 'select' | 'clear' | 're-select';
    previous?: Selected;
    current?: Selected;
    removed?: Selected;
    added?: Selected;
};
export type NeoListMethods<Value = unknown> = {
    /**
     * Scroll the list to the top.
     */
    scrollTop: (options?: ScrollToOptions) => Promise<HTMLElement | false>;
    /**
     * Scroll the list to the bottom.
     */
    scrollBottom: (options?: ScrollToOptions) => Promise<HTMLElement | false>;
    /**
     * Select an item in the list.
     * @param index - The index of the item to select.
     *
     * @returns The selection event if the item was selected, undefined otherwise.
     */
    selectItem: (...selection: NeoListSelectedItem<Value>[]) => NeoListSelectEvent | undefined;
    /**
     * Clear the selected item(s).
     * If no index is provided, all items will be cleared.
     *
     * @returns The selection event if the list or item was cleared, undefined otherwise.
     */
    clearItem: (...selection: NeoListSelectedItem<Value>[]) => NeoListSelectEvent | undefined;
    /**
     * Clear all items in the list then re-select the previously selected item(s) only if they still exist in the list.
     *
     * @note Requires the `id` property to be set and unique for each item.
     * @returns The selection event if the list or item was cleared, undefined otherwise.
     */
    reSelect: () => NeoListSelectEvent | undefined;
};
export type NeoListItemOrSection<Value = unknown> = NeoListItem<Value> | NeoListSection<Value>;
export type NeoListState<Selected = undefined | NeoListSelectedItem | NeoListSelectedItem[]> = {
    /**
     * List items to display.
     */
    items?: NeoListItemOrSection[];
    /**
     * Whether to allow selecting items in the list.
     */
    select?: boolean;
    /**
     * Whether to allow multiple items in the selection.
     */
    multiple?: boolean;
    /**
     * Whether to allow deselecting items if it will result in an empty selection.
     */
    nullable?: boolean;
    /**
     * The currently selected item(s).
     */
    selected?: Selected;
    /**
     * Optional filter to highlight text.
     */
    highlight?: string;
    /**
     * A filter function to apply to each item in the list.
     * @param item
     */
    filter?: (item: NeoListItemOrSection) => boolean;
    /**
     * A sort function to apply to the list items.
     * @param a
     * @param b
     */
    sort?: (a: NeoListItemOrSection, b: NeoListItemOrSection) => number;
    /**
     * If the list is currently loading additional items.
     */
    loading?: boolean;
    /**
     * If the list should display a loading skeleton.
     */
    skeleton?: boolean;
    /**
     * Disable all items in the list.
     */
    disabled?: boolean;
    /**
     * Disable selection for all items in the list.
     */
    readonly?: boolean;
    /**
     * Inverts the flow of the list (flex-direction: column-reverse).
     */
    reverse?: boolean;
};
export type NeoListContext<Selected = NeoListSelectedItem | NeoListSelectedItem[]> = NeoListState<Selected> & NeoListMethods;
export type NeoListProps<Value = unknown, Tag extends keyof HTMLElementTagNameMap = 'ul', Selected = NeoListSelectedItem | NeoListSelectedItem[]> = {
    /**
     * Optional snippet to display in place of each list item.
     */
    item?: NeoListItemRender<Value>;
    /**
     * Optional snippet to display in place of each list section.
     */
    section?: NeoListSectionRender<Value>;
    /**
     * Optional snippet to display when the list is empty.
     */
    empty?: Snippet<[NeoListContext]>;
    /**
     * Optional snippet to display in place of the loading indicator.
     */
    loader?: Snippet<[NeoListContext]>;
    /**
     * Optional snippet to display after the list.
     */
    after?: Snippet<[NeoListContext]>;
    /**
     * Optional snippet to display before the list.
     */
    before?: Snippet<[NeoListContext]>;
    /**
     * Optional snippet to display inside the list.
     */
    children?: Snippet<[NeoListContext]>;
    /**
     * Transition function to apply when removing items from the list.
     * Note: unique `id` is required for entering/leaving transitions.
     */
    animate?: HTMAnimationProps['animate'];
    /**
     * Transition function to apply when adding items to the list.
     * Note: unique `id` is required for entering/leaving transitions.
     */
    in?: HTMLTransitionProps['in'];
    /**
     * Transition function to apply when removing items from the list.
     * Note: unique `id` is required for entering/leaving transitions.
     */
    out?: HTMLTransitionProps['out'];
    /**
     * Whether to dim the opacity of inactive tabs on hover.
     */
    dim?: boolean;
    /**
     * Whether to display a shadow when scrolling content.
     *
     * @default true
     */
    shadow?: boolean;
    /**
     * Overrides the default scrollbars.
     */
    scrollbar?: boolean;
    /**
     * Whether to scroll to the bottom when loading additional items.
     *
     * @default false
     */
    scrollToLoader?: boolean;
    /**
     * Optional flex strategy for the container
     */
    flex?: CSSStyleDeclaration['flex'];
    /**
     * Optional list width constraints.
     */
    width?: SizeInput<'width'>;
    /**
     * Optional list height constraints.
     */
    height?: SizeInput<'height'>;
    /**
     * The HTML tag to use for the list.
     * @default 'ul'
     */
    tag?: Tag | keyof HTMLElementTagNameMap;
    /**
     * Event listener that fires when an item is selected/deselected.
     * @param event
     */
    onSelect?: (event: NeoListSelectEvent<Selected>) => void;
    /**
     * The props to pass to the list container.
     */
    containerProps?: HTMLNeoBaseElement & HTMLTagProps;
    /**
     * The props to pass to the loader.
     */
    loaderProps?: NeoListBaseLoaderProps;
    /**
     * Optional props to pass to the button.
     */
    buttonProps?: NeoButtonProps;
    /**
     * Optional props to pass to the divider.
     */
    dividerProps?: NeoDividerProps;
    /**
     * Optional props to pass to the list item.
     */
    itemProps?: Omit<NeoListBaseItemProps<Value>, 'buttonProps'>;
    /**
     * Optional props to pass to the list section.
     */
    sectionProps?: NeoListBaseSectionProps<Value, Tag>;
} & HTMLRefProps & HTMLNeoBaseElement<HTMLElementTagNameMap[Tag]> & NeoListState<Selected>;
export type NeoListHTMLElement<Value = unknown, Tag extends keyof HTMLElementTagNameMap = 'ul'> = HTMLNeoBaseElement<HTMLElementTagNameMap[Tag]> & NeoListMethods<Value>;
export declare const findByIdInList: <Value = unknown>(selection: NeoListSelectedItem<Value>, array: NeoListItemOrSection<Value>[]) => NeoListSelectedItem<Value> | undefined;
export declare const findByValueInList: <Value = unknown>(value: Value, array: NeoListItemOrSection<Value>[]) => NeoListSelectedItem<Value> | undefined;
