import { nothing, PropertyValues, TemplateResult } from 'lit';
import type { IconType } from '../../../md/icons/Icons.js';
import ApiElement from '../../ApiElement.js';
import '../../../md/icons/ui-icon.js';
import '../../../md/icon-button/ui-icon-button.js';
export interface ISelectDetail {
    /**
     * The key of the selected item
     */
    key: string;
    /**
     * THe kind of the selected item
     */
    kind: string;
    /**
     * Optionally, the parent odf the selected item, if any.
     */
    parent?: string;
    /**
     * When applicable, the top object in the structure.
     */
    root?: string;
}
export interface IListItemRenderOptions {
    draggable?: boolean;
    parent?: string;
    disabled?: boolean;
    /**
     * Only relevant for parent list item.
     * When set it forces this icon to be rendered next to the toggle button.
     */
    parentIcon?: IconType;
    /**
     * When set is add the `data-root` attribute.
     * In principle, it represents a root object in the tree, if any.
     */
    root?: string;
}
/**
 * A base class for navigation elements helping creating specific implementation of the view.
 * The implementations sets their own properties with the data that are used to generate the view.
 *
 * The generated menu must have the following structure created by the implementations:
 *
 * ```html
 * <ul aria-label="..." aria-multiselectable="false">
 *  <li role="treeitem" data-key="..." data-kind="..." data-draggable="true|false">
 *    <div class="list-item-content"><span class="label" title="...">...</span></div>
 *  </li>
 *  <li role="treeitem" data-key="..." data-kind="..." data-draggable="true" aria-expanded="true" class="parent-item">
 *    <div class="list-item-content">
 *      <ui-icon icon="chevronRight" class="group-toggle-icon"></ui-icon>
 *      <span class="label" title="...">...</span>
 *    </div>
 *    <ul role="group" data-parent="..." ?hidden aria-hidden="true|false">
 *      <li role="treeitem" data-key="..." data-parent="..." data-kind="..." data-draggable="true|false">
 *        <div class="list-item-content">
 *          <ui-icon icon="..." class="item-icon"></ui-icon>
 *          <span class="label" title="...">...</span>
 *        </div>
 *      </li>
 *    </ul>
 *  </li>
 * </ul>
 * ```
 *
 * Additionally, the child element must include styles from './AppNavigation.styles.js`.
 *
 * Assumptions when running the menu:
 *
 * - all `li` items that do not have `aria-disabled` attribute are considered active tree items (learn more why not to use "disabled" attribute https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-disabled)
 * - all `li` elements have `data-key` and `data-kind` attributes set. Elements without these properties are ignored.
 * - all `ul` and `li` elements that have a parent also have `data-parent` with the value of the parent's key.
 *    When this is not set the element is considered a top level element.
 * - the implementations does not manage the `tabindex` of any item. Instead set the `_focusedItem` to
 *    the currently focused element and the base will manage the focus for you (after the update is complete).
 *
 * @fires {CustomEvent} select - Custom, non bubbling event when a selection is made.
 *        It has the `key` and `kind` properties on the detail panel with optional `parent` id.
 * @fires {Event} deselect - Custom, non bubbling event when the selection is cleared.
 */
export default class AppNavigation extends ApiElement {
    /**
     * The list of keys of opened items with children. This should be clear each time
     * when the main data property change.
     */
    protected opened: Set<string>;
    /**
     * The key of the currently focused item.
     */
    protected focused?: string;
    /**
     * The currently focused node.
     * In case there are headers in the list, this may not be a list item.
     */
    accessor focusedItem: HTMLElement | undefined;
    /**
     * To be set in the child class constructor to configure whether a name change is possible.
     */
    protected allowRename?: boolean;
    /**
     * The currently selected navigation item.
     * @attr
     */
    accessor selected: string | undefined;
    /**
     * When set it renders a name change input for the item.
     * This is the `key` of the object.
     *
     * Note, when the user finish editing the name it calls the `_commitName(key, kind, name)` method.
     * This requires the `_allowRename` property to be set to `true` in the constructor.
     * @attr
     */
    accessor edited: string | undefined;
    /**
     * When set it prohibits the element to make visual selection (via the css) when an item is selected.
     * This is helpful when one navigation can be visually references in multiple places (like split layout).
     * @attr
     */
    accessor noVisualSelection: boolean | undefined;
    /**
     * A reference to the currently rendered name input, if any.
     */
    protected accessor _nameInput: HTMLInputElement | null;
    /**
     * When set it adds a menu entry with the navigation label.
     * @attribute
     */
    accessor label: string | undefined;
    /**
     * A reference to the currently dragged item.
     * This logic assumes that the drag and drop is local to this element.
     */
    protected draggingItem?: HTMLLIElement;
    constructor();
    connectedCallback(): void;
    protected willUpdate(cp: PropertyValues<this>): void;
    protected updated(cp: PropertyValues<this>): void;
    protected reset(): void;
    /**
     * This method is called when the `_focusedItem` property is updated.
     * It removes tabindex from the old element (if any) and sets tabindex and focuses on the new item (if any).
     * When there's no new item, it sets the `tabindex` on self.
     *
     * @param current The new focused element, if any
     * @param old The old focused element, if any.
     */
    protected manageFocus(current?: HTMLElement, old?: HTMLElement): void;
    /**
     * Makes sure the node represented by the passed key is visible in the UI.
     * This opens all parents on the way up to the root and scrolls to the node, when needed.
     * @param key The key of the object to ensure visibility for.
     */
    ensureTreeVisibility(key: string): void;
    /**
     * Toggles a group of tree items.
     *
     * @param key The key of the group parent.
     */
    toggleGroup(key: string): void;
    /**
     * Allows to programmatically open a folder.
     * It opens all parents if they are not opened.
     * @param key The key of the folder to open.
     */
    openGroup(key: string): void;
    /**
     * Allows to programmatically close a folder.
     * @param key The key of the folder to open.
     */
    closeGroup(key: string): void;
    /**
     * A function to determine whether the passed Element is an active list item.
     *
     * @param node The Element to test
     * @returns true when the passed element is a `li` element and is not disabled.
     */
    protected isValidListItem(node: Element): boolean;
    /**
     * Marks the item as currently focused.
     *
     * Note, focused item is not the same as selected item. Focus is reflected in the UI without changing the selection.
     *
     * Also note, this only sets the `_focused` and `_focusedItem` properties. After the element renders
     * the implementation should change the `tabindex` of the focused item to `0`.
     */
    protected focusListItem(node: HTMLElement): void;
    /**
     * Finds a valid list item that is a parent to the current item.
     *
     * @param node The current node located somewhere in the tree.
     * @returns The nearest parent list item or undefined when not found.
     */
    protected findParentListItem(node: HTMLElement): HTMLLIElement | undefined;
    /**
     * From a `<li>` it finds the last `<li>` descendant in the tree.
     *
     * ```html
     * <ul>
     *  <li> <-- this is the current node
     *    <div>...</div>
     *    <ul>
     *       <li>...</li>
     *       <li>  <-- this is the last list item.
     *          <div>...</div>
     *          <ul hidden> <- this is ignored.
     *            <li></li>
     *            <li></li>  <-- this is not the last list item because the parent list is hidden.
     *          </ul>
     *      </li>
     *    </ul>
     *  </li>
     * </ul>
     * ```
     *
     * @param node The current list item to find the last descendant for.
     * @returns The last list item or undefined.
     */
    protected findLastDescendant(node: HTMLElement): HTMLElement | undefined;
    /**
     * Focuses on a list descendant of a folder item.
     * It does nothing when the `node` is not a folder item or the folder has no selectable children.
     *
     * @param node The node to use as a reference. The current focused node by default.
     * @returns true when focused on any of the descendants
     */
    protected focusFirstDescendant(node?: HTMLElement | undefined): boolean;
    /**
     * Focuses on the next node relative to the passed node.
     *
     * @param node The node to use as a starting point. When not set it uses the currently focused node.
     * @returns true when focused on any of the next siblings
     */
    focusNextSibling(node?: HTMLElement | undefined): boolean;
    /**
     * Focuses on the previous node relative to the passed node.
     *
     * @param node The node to use as a starting point. When not set it uses the currently focused node.
     * @returns true when focused on any of the previous siblings
     */
    focusPreviousSibling(node?: HTMLElement | undefined): boolean;
    /**
     * Focuses on a first list item that accepts focus relative to the given node.
     *
     * @param node The node to use as a reference. The current focused node by default.
     * @returns true when focused on any of the parents
     */
    protected focusFirstParent(node: HTMLElement): boolean;
    protected findClosestListItem(e: Event): HTMLLIElement | undefined;
    /**
     * Dispatched the `select` custom event with the `key` and `kind` on the detail.
     *
     * @param key The key of the selected item.
     * @param kind The kind of the selected item
     * @param parent Optional parent item.
     */
    protected notifySelection(key: string, kind: string, parent?: string, root?: string): void;
    /**
     * A handler for the `dragstart` event dispatched when the item is draggable.
     * Calls the `setupDataTransfer()` if has valid target.
     */
    protected handleItemDragStart(e: DragEvent): void;
    /**
     * A handler for the `dragend` event dispatched when the item is draggable.
     * @param e The dragend event.
     */
    protected handleItemDragEnd(e: DragEvent): void;
    protected handleItemDragOver(e: DragEvent): void;
    protected handleItemDragLeave(e: DragEvent): void;
    protected handleItemDrop(e: DragEvent): void;
    /**
     * Sets the common properties on the `DataTransfer`. Implementations can override this method to add
     * own properties.
     */
    protected setupDataTransfer(item: HTMLLIElement, dt: DataTransfer): void;
    protected unloadDataTransfer(item: HTMLLIElement, dt: DataTransfer): void;
    protected handleNameInputKeydown(e: KeyboardEvent): void;
    /**
     * Handles an event when something is dragged over another item.
     * Mind that it can be anything (files, text, etc.) so the implementation should
     * check the type of the data transfer.
     *
     * @param item The item that an object is dragged overt that item.
     * @param dt Data transfer instance.
     * @param validTarget True when the target is a valid drop target.
     */
    protected processDragOver(item: HTMLLIElement, dt: DataTransfer, validTarget: boolean): void | Promise<void>;
    protected processDragLeave(item: HTMLLIElement, dt: DataTransfer): void | Promise<void>;
    protected processDrop(item: HTMLLIElement, dt: DataTransfer): void | Promise<void>;
    /**
     * To be implemented by the child class.
     * Checks whether the target is a valid drop target.
     * When used, it simplifies the sub-class logic by using this classes drag and drop handling.
     * @param target The target item that the object is dragged over.
     * @param dt The data transfer instance.
     * @returns true when the target is a valid drop target.
     */
    protected isValidDropTarget(target: HTMLElement, dt: DataTransfer): boolean;
    /**
     * A map of timeouts for opening groups.
     */
    private groupOpenTimeouts;
    /**
     * Schedules opening a group after a delay.
     * @param key The key of the group to open.
     * @param item The list item element.
     */
    private scheduleGroupOpen;
    /**
     * Cancels a scheduled group open.
     * @param key The key of the group to cancel.
     */
    private cancelGroupOpen;
    protected handleNameCommit(e: Event): void;
    /**
     * This should be overwritten by the implementation that support name change.
     * Method called when the user request to change a name of an item.
     *
     * @param key The key of the item.
     * @param kind The kind of the item.
     * @param name THe new name.
     */
    protected commitName(key: string, kind: string, name: string): void | Promise<void>;
    protected handleDoubleClick(e: Event): void;
    protected handleClick(e: Event): void;
    protected handleKeydown(e: KeyboardEvent): void;
    protected renderLabel(): TemplateResult | typeof nothing;
    protected deselect(): void;
    /**
     * Performs the default action of the currently focused node.
     * For parent nodes, it opens or closes the node.
     * In single-select trees, if the node has no children, selects the current node
     * if not already selected (which is the default action).
     */
    protected handleEnterAction(node: HTMLElement): void;
    /**
     * 1. When focus is on a closed node, opens the node; focus does not move.
     * 2. When focus is on a open node, moves focus to the first child node.
     * 3. When focus is on an end node (a tree item with no children), does nothing.
     */
    protected handleRightAction(node: HTMLElement): void;
    /**
     * 1. When focus is on an open node, closes the node.
     * 2. When focus is on a child node that is also either an end node or a closed node, moves focus to its parent node.
     * 3. When focus is on a closed `tree`, does nothing.
     */
    protected handleLeftAction(node: HTMLElement): void;
    /**
     * Moves focus to the next node that is focusable without opening or closing a node.
     */
    protected handleDownAction(node: HTMLElement): void;
    /**
     * Moves focus to the previous node that is focusable without opening or closing a node.
     */
    protected handleUpAction(node: HTMLElement): void;
    protected handleHomeAction(): void;
    protected handleEndAction(): void;
    /**
     *
     * @param contents The children contents.
     * @returns A predefined template for the outer list element.
     */
    protected renderOuterList(contents: TemplateResult | TemplateResult[] | string): TemplateResult;
    protected renderParentListItem(key: string, kind: string, label: string, children: TemplateResult | TemplateResult[] | string, opts?: IListItemRenderOptions): TemplateResult;
    protected renderParentListItemContent(label: string, opts?: IListItemRenderOptions): TemplateResult;
    protected renderListItem(key: string, kind: string, label: string, content: TemplateResult | TemplateResult[] | string, opts?: IListItemRenderOptions): TemplateResult;
    protected renderNameInput(key: string, kind: string, oldName?: string): TemplateResult;
    protected renderItemContent(icon: IconType, label: string): TemplateResult;
}
//# sourceMappingURL=AppNavigationElement.d.ts.map