type ID = string | number | bigint;
type StrictAccessor<Data> = string | ((item: Data) => ID);
type Accessor<Data> = string | ((item: Data) => ID | undefined);

type SelectItem<Data, Meta> = {
    id: ID;
    data: Data;
    isSelected: boolean;
    meta?: Meta;
    select: () => void;
    unselect: () => void;
    toggle: () => void;
};
interface ItemDef<Data, Meta> {
    id_accessor: StrictAccessor<Data>;
    meta?: (item: Data) => Meta;
}

interface Scheduler {
    schedule(fn: () => void): void;
}

interface MultiSelectFilter<Data, Meta> {
    query: string;
    predicate: (item: Data, query: string, meta: Meta) => boolean;
}

interface ScopeOptions {
    filteredOnly?: boolean;
}
interface UnifiedGroupNode<Data, Meta, GroupMeta = unknown> {
    key: ID;
    level: number;
    path: ID[];
    getItems(options?: ScopeOptions): SelectItem<Data, Meta>[];
    getSubGroups(options?: ScopeOptions): UnifiedGroupNode<Data, Meta, GroupMeta>[];
    getSubGroup(key: ID): UnifiedGroupNode<Data, Meta, GroupMeta> | undefined;
    hasSubGroups(options?: ScopeOptions): boolean;
    select(options?: {
        filteredOnly?: boolean;
    }): void;
    unselect(options?: {
        filteredOnly?: boolean;
    }): void;
    toggle(options?: {
        filteredOnly?: boolean;
    }): void;
    isAllSelected(options?: {
        filteredOnly?: boolean;
    }): boolean;
    totalCount: number;
    filteredCount: number;
    getMeta(): GroupMeta | undefined;
}

interface GroupTreeOptions {
    filter?: {
        filteredOnly?: boolean;
    };
    selection?: {
        selectedOnly?: boolean;
        includePartial?: boolean;
    };
}

type PositionStrategy = (indices: number[]) => number;
declare const CollapsePositionFirst: PositionStrategy;
declare const CollapsePositionLast: PositionStrategy;
type CollapsedNode<Data, Meta, GroupMeta = unknown> = {
    type: "item";
    node: SelectItem<Data, Meta>;
    order: number;
} | {
    type: "group";
    node: UnifiedGroupNode<Data, Meta, GroupMeta>;
    order: number;
};
interface CollapseOptions {
    filteredOnly?: boolean;
    positionStrategy?: PositionStrategy;
}
declare function collapseSelection<Data, Meta, GroupMeta = unknown>(tree: UnifiedGroupNode<Data, Meta, GroupMeta>[], orderMap: Map<ID, number>, options?: CollapseOptions): CollapsedNode<Data, Meta, GroupMeta>[];

interface GroupByDescriptor<Data, Meta = unknown, GroupMeta = unknown> {
    accessor: Accessor<Data>;
    getMeta?: (groupKey: ID, items: Data[], level: number) => GroupMeta;
}
interface MultiSelectState {
    selectedIds: Set<ID>;
}
interface MultiSelectOptions<Data, Meta = unknown, GroupMeta = unknown> {
    data: Data[];
    itemDef: ItemDef<Data, Meta>;
    initialState?: Omit<MultiSelectState, "selectedIds"> & {
        selectedIds: Array<ID>;
    };
    filter?: MultiSelectFilter<Data, Meta>;
    scheduler?: Scheduler;
    groupBy?: Array<Accessor<Data> | GroupByDescriptor<Data, Meta, GroupMeta>>;
}
type Listener = (state: MultiSelectState, diff: {
    added: ID[];
    removed: ID[];
}) => void;
interface MultiSelect<Data, Meta = unknown, GroupMeta = unknown> {
    subscribe(listener: Listener): () => void;
    getItems(): SelectItem<Data, Meta>[];
    getSelectedIds(options?: {
        filteredOnly?: boolean;
    }): ID[];
    getSelectedItems(options?: {
        filteredOnly?: boolean;
    }): SelectItem<Data, Meta>[];
    isAllSelected(): boolean;
    selectAll(): void;
    unselectAll(): void;
    toggleAll(): void;
    getFilteredItems(): SelectItem<Data, Meta>[];
    isAllFilteredSelected(): boolean;
    selectAllFiltered(): void;
    unselectAllFiltered(): void;
    toggleAllFiltered(): void;
    setFilter(filter?: MultiSelectFilter<Data, Meta>): void;
    getGroupTree(options?: GroupTreeOptions): UnifiedGroupNode<Data, Meta, GroupMeta>[];
    getSelectionSummary(options?: {
        filteredOnly?: boolean;
    }): {
        total: number;
        selected: number;
    };
    getCollapsedSelection(options?: CollapseOptions): CollapsedNode<Data, Meta, GroupMeta>[];
    getGroup(key: ID): UnifiedGroupNode<Data, Meta, GroupMeta> | undefined;
    getItem(key: ID): SelectItem<Data, Meta> | undefined;
    getGroupMeta(groupKey: ID): GroupMeta | undefined;
}
declare function createMultiSelect<Data, Meta = unknown, GroupMeta = unknown>(options: MultiSelectOptions<Data, Meta, GroupMeta>): MultiSelect<Data, Meta, GroupMeta>;

declare class CollapseManager<Data, Meta = unknown, GroupMeta = unknown> {
    private ms;
    private orderMap;
    private counter;
    constructor(ms: MultiSelect<Data, Meta, GroupMeta>);
    getCollapsedSelection(options?: CollapseOptions): CollapsedNode<Data, Meta, GroupMeta>[];
}

declare function useMultiSelect<Data, Meta = unknown, GroupMeta = unknown>(options: MultiSelectOptions<Data, Meta, GroupMeta>): MultiSelect<Data, Meta, GroupMeta>;

export { CollapseManager, type CollapseOptions, CollapsePositionFirst, CollapsePositionLast, type CollapsedNode, type MultiSelect, type MultiSelectOptions, type MultiSelectState, type PositionStrategy, type SelectItem, type UnifiedGroupNode, collapseSelection, createMultiSelect, useMultiSelect };
