/**
 * @license
 * Copyright 2025 Kai-Orion & Sandlada
 * SPDX-License-Identifier: MIT
 */
import type { ReactiveController, ReactiveControllerHost } from 'lit';
/**
 * Minimum shape required of any element that acts as a host for
 * `SelectionController`. Satisfied by `MDCTogglableButton` and any other
 * form-associated custom element that participates in a named selection group.
 */
export interface ISelectionControllerHost extends HTMLElement {
    /** Whether this control is currently selected / checked. */
    checked: boolean;
    /** When true the control is non-interactive and ignored by navigation. */
    disabled?: boolean;
    /** Used by roving-tabindex management. */
    tabIndex: number;
    /** Controls that share the same `name` form a mutual-exclusion group (radio behaviour). */
    name?: string;
}
/**
 * Configuration options for `SelectionController`.
 * All fields are optional – unspecified fields retain their defaults.
 */
export interface ISelectionControllerOptions {
    /**
     * When `true` the group behaves like checkboxes: each item can be toggled
     * independently and no mutual-exclusion enforcement is applied.
     * When `false` the group behaves like radio buttons: selecting one item
     * automatically deselects all siblings that share the same `name`.
     * @default false
     */
    multiple: boolean;
    /**
     * When `true` clicking an already-selected control deselects it (toggle).
     * Typically `true` for checkbox groups and `false` for radio groups.
     * @default false
     */
    canCancel: boolean;
    /**
     * When `true`, receiving focus does NOT automatically select the focused
     * control (useful for checkbox groups where focus and selection are
     * independent).
     * @default false
     */
    preventSelectionDuringInitialFocus: boolean;
    /**
     * When `true`, moving focus between controls with arrow keys does NOT
     * automatically select the newly focused control.
     * @default false
     */
    preventSelectionDuringSwitching: boolean;
    /**
     * When `true`, a synthetic `click` is dispatched on the newly focused
     * control after each arrow-key navigation. This fires ripple press
     * animations and other click-based visual effects without re-triggering
     * `toggleSelection()` (the click is internally suppressed for that purpose).
     *
     * Enable for radio-button groups; leave `false` for focus-only groups such
     * as checkbox lists where arrow keys move focus without selecting.
     * @default false
     */
    dispatchNavigationClick: boolean;
    /**
     * Controls whether `SelectionController` dispatches native `input` and
     * `change` events when selection changes.
     *
     * Set to `false` when the host component needs to dispatch custom events
     * with richer payloads or custom timing.
     * @default true
     */
    dispatchInputChangeEvents: boolean;
    /**
     * Returns the focusable DOM element for a given host.
     * Defaults to returning the host itself.
     */
    getFocusableElement: (host: ISelectionControllerHost) => HTMLElement;
    /** Called once after `hostConnected()` completes. */
    onConnected: (host: ISelectionControllerHost) => void;
    /** Called once after `hostDisconnected()` completes. */
    onDisconnected: (host: ISelectionControllerHost) => void;
    /** Called immediately before `host.checked` is mutated by `toggleSelection()`. */
    onBeforeSelect: (host: ISelectionControllerHost) => void;
    /** Called immediately after `host.checked` is mutated by `toggleSelection()`. */
    onAfterSelected: (host: ISelectionControllerHost) => void;
    /**
     * Called after `moveFocus()` completes on the **newly focused** host.
     * Fires after `.focus()`, state mutation, `input`/`change` events, and the
     * optional navigation click have all been dispatched.
     *
     * Use this to perform visual effects that depend on `:focus-visible` not
     * being reliable (e.g. force-opening a focus ring for a custom element that
     * browsers may not grant `:focus-visible` to on programmatic focus).
     *
     * @param next - the host that just received focus via keyboard navigation.
     */
    onAfterNavigate: (next: ISelectionControllerHost) => void;
}
/**
 * A `ReactiveController` that adds radio/checkbox selection semantics,
 * keyboard navigation, and roving-tabindex management to a custom element.
 *
 * ### Group discovery
 * Controls are grouped by the value of their `name` attribute, queried from
 * the host's root node (shadow root or document). This mirrors native
 * `<input type="radio">` / `<input type="checkbox">` behaviour where any
 * element with the same `name` – regardless of tag name – belongs to the
 * same logical group.
 *
 * ### Usage
 * ```ts
 * class MyToggle extends LitElement {
 *   private readonly selectionController = new SelectionController(this, {
 *     multiple: false,
 *     canCancel: false,
 *   })
 *   // host.addController(this.selectionController) not required here;
 *   // SelectionController calls host.addController internally.
 * }
 * ```
 */
export declare class SelectionController implements ReactiveController {
    private readonly host;
    private root;
    /** @see ISelectionControllerOptions.multiple */
    multiple: boolean;
    /** @see ISelectionControllerOptions.canCancel */
    canCancel: boolean;
    /** @see ISelectionControllerOptions.preventSelectionDuringInitialFocus */
    preventSelectionDuringInitialFocus: boolean;
    /** @see ISelectionControllerOptions.preventSelectionDuringSwitching */
    preventSelectionDuringSwitching: boolean;
    /** @see ISelectionControllerOptions.dispatchNavigationClick */
    dispatchNavigationClick: boolean;
    /** @see ISelectionControllerOptions.dispatchInputChangeEvents */
    dispatchInputChangeEvents: boolean;
    /** @see ISelectionControllerOptions.getFocusableElement */
    getFocusableElement: (host: ISelectionControllerHost) => HTMLElement;
    /** @see ISelectionControllerOptions.onConnected */
    onConnected: (host: ISelectionControllerHost) => void;
    /** @see ISelectionControllerOptions.onDisconnected */
    onDisconnected: (host: ISelectionControllerHost) => void;
    /** @see ISelectionControllerOptions.onBeforeSelect */
    onBeforeSelect: (host: ISelectionControllerHost) => void;
    /** @see ISelectionControllerOptions.onAfterSelected */
    onAfterSelected: (host: ISelectionControllerHost) => void;
    /** @see ISelectionControllerOptions.onAfterNavigate */
    onAfterNavigate: (next: ISelectionControllerHost) => void;
    constructor(host: ISelectionControllerHost & ReactiveControllerHost, options?: Partial<ISelectionControllerOptions>);
    /**
     * Atomically updates any subset of controller options.
     * Useful when a host property (e.g. `type`) changes and several behavioural
     * flags must be updated together.
     *
     * @example
     * ```ts
     * this.selectionController.configure({
     *   multiple: false,
     *   canCancel: false,
     *   preventSelectionDuringInitialFocus: false,
     *   preventSelectionDuringSwitching: false,
     * })
     * ```
     */
    configure(options: Partial<ISelectionControllerOptions>): void;
    /**
     * Returns all controls that belong to the same selection group as the host.
     * A group is defined by matching `name` attribute values within the host's
     * root node (shadow root or document).
     *
     * When the host has no `name`, or is not connected, returns `[host]`.
     */
    get controls(): ISelectionControllerHost[];
    /**
     * Toggles or selects the host according to the current `canCancel` /
     * `multiple` settings, then enforces mutex consistency for radio groups
     * and updates the roving tabindex.
     *
     * No-op when the host is disabled.
     */
    toggleSelection(): void;
    /**
     * Called when the host's `checked` property changes programmatically
     * (i.e. outside of `toggleSelection()`), for example from a property
     * setter. Enforces mutex consistency for radio groups and refreshes the
     * roving tabindex.
     *
     * @example
     * ```ts
     * set checked(value: boolean) {
     *   this._checked = value;
     *   this.selectionController.handleCheckedChange();
     * }
     * ```
     */
    handleCheckedChange(): void;
    /**
     * Ensures that only the host is checked within its group.
     * No-op when `multiple` is true or the host itself is not checked.
     */
    enforceMutexConsistency(): void;
    private updateRovingTabindex;
    /**
     * Moves focus in the given direction, skipping disabled controls.
     * Falls back to keeping focus on the current host if no enabled sibling
     * is found.
     */
    private moveFocus;
    /**
     * When Space / Enter toggles the selection we also dispatch a synthetic
     * (non-composed) click on the host so that visual effects — ripple,
     * activation-click forwarding — fire exactly as they do for pointer clicks.
     *
     * This flag prevents that synthetic click from triggering a second
     * `toggleSelection()` inside `handleClick`.
     */
    private _suppressNextClick;
    /**
     * Hosts registered here are expecting a navigation click dispatched by
     * `moveFocus()`. `handleClick` on that host will skip `toggleSelection()`
     * so only visual effects (ripple press animation) are triggered.
     */
    private static readonly _pendingNavigationClick;
    /**
     * `true` while a pointer (mouse / touch) is physically held down on the host.
     *
     * Used by `handleFocus` to suppress auto-selection when a mouse click
     * causes focus before the `click` event fires: without this guard,
     * `handleFocus` would set `checked = true` for radio controls, making
     * `toggleSelection()` see no state change and therefore not dispatch
     * `input` / `change` events.
     */
    private _pointerIsDown;
    private readonly handlePointerDown;
    private readonly handlePointerUp;
    private readonly handleFocus;
    private readonly handleClick;
    private readonly handleKeyDown;
    hostConnected(): void;
    hostDisconnected(): void;
    hostUpdated(): void;
}
//# sourceMappingURL=selection-controller.d.ts.map