import { CanvasViewport } from './CanvasViewport.js';
import { FocusType } from './FocusType.js';
import { Theme } from '../theme/Theme.js';
import { WidgetEvent } from '../events/WidgetEvent.js';
import type { PointerStyleHandler } from './PointerStyleHandler.js';
import type { LayoutConstraints } from './LayoutConstraints.js';
import { type TextInputHandler, type TextInputHandlerListener } from './TextInputHandler.js';
import type { Widget } from '../widgets/Widget.js';
import type { Driver } from './Driver.js';
import type { CaptureList } from './CaptureList.js';
import type { WidgetEventEmitter, WidgetEventListener } from '../events/WidgetEventEmitter.js';
import { type Rect } from '../helpers/Rect.js';
/**
 * Allowed cursor styles and in order of priority; lower indices have higher
 * priority
 */
export declare const ALLOWED_CURSOR_STYLES: string[];
/**
 * Optional Root constructor properties.
 *
 * @category Core
 */
export interface RootProperties {
    /** Sets {@link Root#pointerStyleHandler}. */
    pointerStyleHandler?: PointerStyleHandler | null;
    /** Sets {@link Root#child}'s {@link Widget#inheritedTheme}. */
    theme?: Theme;
    /** Sets {@link Root#resolution}. */
    resolution?: number;
    /** Sets {@link Root#preventBleeding}. */
    preventBleeding?: boolean;
    /**
     * Sets {@link CanvasViewport#preventAtlasBleeding} in the internal viewport
     * ({@link Root#viewport}).
     */
    preventAtlasBleeding?: boolean;
    /** The starting width of the {@link Root#viewport}'s canvas. */
    canvasStartingWidth?: number;
    /** The starting height of the {@link Root#viewport}'s canvas. */
    canvasStartingHeight?: number;
    /** The starting layout constraints of the Root. */
    constraints?: LayoutConstraints;
    /** Sets {@link Root#maxCanvasWidth}. */
    maxCanvasWidth?: number;
    /** Sets {@link Root#maxCanvasHeight}. */
    maxCanvasHeight?: number;
    /** Sets {@link Root#tabFocusable}. */
    tabFocusable?: boolean;
}
/**
 * A Root is the parent of all widgets, but not a widget itself. It contains a
 * single child and manages dimensions and input handling
 *
 * @category Core
 */
export declare class Root implements WidgetEventEmitter {
    /** Typed user listeners attached to this Root */
    private typedListeners;
    /** Untyped user listeners attached to this Root */
    private untypedListeners;
    /** Next user listener ID */
    private nextListener;
    /** A one-way map from an ID to a descendant Widget. Internal use only. */
    private idMap;
    /** The internal viewport. Manages drawing */
    protected viewport: CanvasViewport;
    /** The list of drivers registered to this root */
    protected drivers: Set<Driver>;
    /**
     * Is the Root enabled? For internal use only.
     *
     * See {@link Root#enabled}
     */
    protected _enabled: boolean;
    /**
     * For internal use only. Current value of {@link Root#pointerStyleHandler}.
     */
    protected _pointerStyleHandler: PointerStyleHandler | null;
    /**
     * Current component foci (event targets for each focus type).
     *
     * For internal use only.
     *
     * See {@link Root#requestFocus}, {@link Root#dropFocus},
     * {@link Root#clearFocus} and {@link Root#getFocus}
     */
    protected _foci: Map<FocusType, Widget | null>;
    /**
     * Last capturer of each component focus (event targets for each focus
     * type).
     *
     * For internal use only.
     *
     * See {@link Root#getFocusCapturer}
     */
    protected _fociCapturers: Map<FocusType, Widget | null>;
    /**
     * Text input handler constructor for environments where getting keyboard
     * input is hard, such as mobile and WebXR. If not null, widgets that need
     * text may call this to get strings and cursor positions as text is typed.
     *
     * See {@link Root#getTextInput}
     */
    textInputHandler: (new (listener: TextInputHandlerListener) => TextInputHandler) | null;
    /** See {@link Root#currentTextInputHandler}. For internal use only. */
    private _currentTextInputHandler;
    /**
     * Has the warning for poorly captured TabSelectEvent events been issued?
     */
    private static badTabCaptureWarned;
    /**
     * The list of widgets that were hovered in the last check. Will be swapped
     * with {@link Root#hoveredWidgets} every time a pointer event is
     * dispatched. For internal use only.
     */
    private lastHoveredWidgets;
    /**
     * The list of widgets that are currently hovered. Will be swapped with
     * {@link Root#lastHoveredWidgets} every time a pointer event is dispatched.
     * For internal use only.
     */
    private hoveredWidgets;
    /**
     * The list of widgets that had a pointer focus but dropped it while
     * processing an event. For internal use only.
     */
    private droppedPointerFoci;
    /**
     * Currently requested pointer styles. The list is ordered, where higher
     * priority pointer styles have a lower index than lower priority pointer
     * styles; the highest priority pointer style is always at index 0. For
     * internal use only.
     */
    private requestedPointerStyles;
    /**
     * Helper list for {@link requestedPointerStyles} which contains the
     * respective requesters. For internal use only.
     */
    private requestedPointerStyleSources;
    /**
     * Helper list for {@link requestedPointerStyles} which contains the
     * respective requesters' widget. For internal use only.
     */
    private requestedPointerStyleWidgets;
    /**
     * For internal use only. Returns true if the child widget has been detached
     * from the root.
     */
    private hasDetached;
    /**
     * Can tab controls be used in this UI root? True by default. Can only be
     * set once when the UI is created.
     */
    readonly tabFocusable: boolean;
    constructor(child: Widget, properties?: Readonly<RootProperties>);
    /**
     * For internal use only. Sets the pointer style to 'default' if there is a
     * pointer style handler.
     */
    private dropPointerStyleHandler;
    /**
     * For internal use only. Sets the pointer style to the highest priority
     * requested pointer style if there is a pointer style handler, and if there
     * is a requested pointer style.
     */
    private restorePointerStyleHandler;
    /**
     * Pointer style handler, decides how to show the given pointer style.
     * Normally a function which sets the CSS cursor style of the Root's canvas
     */
    get pointerStyleHandler(): PointerStyleHandler | null;
    set pointerStyleHandler(pointerStyleHandler: PointerStyleHandler | null);
    /**
     * Creates a new CanvasViewport instance for a new Root. Normally it
     * wouldn't make sense to separate this from the constructor, but this makes
     * viewport creation hookable, allowing for the creation of debug overlay
     * viewports.
     *
     * @internal
     * @returns Returns a new CanvasViewport (or child class instance) for the Root
     */
    static makeViewport(child: Widget, properties?: Readonly<RootProperties>): CanvasViewport;
    /** The {@link Root#viewport}'s {@link Viewport#constraints | constraints} */
    get constraints(): LayoutConstraints;
    set constraints(constraints: LayoutConstraints);
    /**
     * The {@link Root#viewport}'s
     * {@link CanvasViewport#canvasDimensions | canvasDimensions}
     */
    get canvasDimensions(): [number, number];
    /**
     * The {@link Root#child}'s {@link Widget#dimensions | dimensions}
     */
    get dimensions(): [number, number];
    /**
     * Is this root enabled? If not enabled, painting, updating or resolving
     * layout will do nothing. {@link Root#drivers | Drivers} will also be
     * notified by calling {@link Driver#onEnable} or {@link Driver#onDisable},
     * pointer style will be reset and all {@link Root#_foci | foci} will be
     * cleared ({@link Root#clearFocus}).
     */
    get enabled(): boolean;
    set enabled(newEnabled: boolean);
    /**
     * The {@link Root#viewport}'s {@link CanvasViewport#canvas | canvas}. The
     * canvas must not be modified directly; consider it output-only.
     */
    get canvas(): HTMLCanvasElement;
    /**
     * The text input handler that is currently in use. `null` if none in use.
     *
     * See {@link Root#textInputHandler}.
     */
    get currentTextInputHandler(): TextInputHandler | null;
    /**
     * Resolve the layout of this root. Does nothing if root is disabled.
     *
     * Calls {@link Root#viewport}'s {@link Viewport#resolveLayout} with
     * {@link Root#child}
     *
     * Call this before calling {@link Root#postLayoutUpdate} and after calling
     * {@link Root#preLayoutUpdate}
     *
     * @returns Returns true if the viewport was resized or re-scaled
     */
    resolveLayout(): boolean;
    /**
     * Paint this root's next frame if needed. Does nothing if root is disabled.
     *
     * Calls {@link Root#viewport}'s {@link Viewport#paint} with
     * {@link Root#child}.
     *
     * Call this after calling {@link Root#postLayoutUpdate}.
     *
     * @returns Returns a list of dirty rectangles in the texture's coordinates, or null if the child widget was not repainted. Use this to tell an external 3D library whether to update a mesh's texture or not, and where to update the mesh's texture.
     */
    paint(): null | Array<Rect>;
    /**
     * Dispatches a {@link WidgetEvent} to this root's {@link Root#child} by
     * calling {@link Widget#dispatchEvent}. Updates
     * {@link Root#_fociCapturers | foci capturers} and notifies
     * {@link Root#drivers} by calling {@link Driver#onFocusCapturerChanged} if
     * the capturer changes. Does nothing if root is disabled.
     *
     * Note that if an event with a focus is dispatched and no widget captures
     * the event due to the widget not existing anymore or being disabled, the
     * focus type of the event will be cleared in the root with
     * {@link Root#clearFocus}.
     *
     * Dispatching a single event can result in a chain of dispatched events.
     * These extra events will be returned.
     *
     * @returns Returns a list of dispatched events and whether they were captured.
     */
    dispatchEvent(baseEvent: WidgetEvent): CaptureList;
    /**
     * Do a pre-layout update; calls {@link Root#drivers}' {@link Driver#update}
     * and {@link Root#child}'s {@link Widget#preLayoutUpdate}. Does nothing if
     * root is disabled.
     *
     * Call this before calling {@link Root#resolveLayout}
     */
    preLayoutUpdate(): void;
    /**
     * Do a post-layout update; calls {@link Root#child}'s
     * {@link Widget#postLayoutUpdate}. Does nothing if root is disabled.
     *
     * Call this before calling {@link Root#paint} and after calling
     * {@link Root#resolveLayout}
     */
    postLayoutUpdate(): void;
    /**
     * Internal method similar to {@link requestFocus}, except only a specific
     * focus is given; no partner foci are added.
     */
    private giveFocus;
    /**
     * Sets the current {@link Root#_foci | focus} of a given type to a given
     * widget. If the focus changes, {@link Root#clearFocus} is called and
     * {@link Root#drivers} are notified by calling
     * {@link Driver#onFocusChanged}.
     *
     * If the target widget doesn't capture the dispatched {@link FocusEvent},
     * then the focus is not changed.
     */
    requestFocus(focusType: FocusType, widget: Widget): void;
    /**
     * Clears the current {@link Root#_foci | focus} of a given type if it is
     * currently set to a given widget. Achieved by calling
     * {@link Root#clearFocus}.
     */
    dropFocus(focusType: FocusType, widget: Widget): void;
    /**
     * Clears all the {@link Root#_foci | foci} that are set to a given Widget.
     * Achieved by calling {@link Root#dropFocus}
     */
    dropFoci(widget: Widget): void;
    /**
     * Clears the current {@link Root#_foci | focus} of a given type. If there
     * was a focus set, {@link Root#drivers} are notified by calling
     * {@link Driver#onFocusChanged}.
     */
    clearFocus(focusType: FocusType): void;
    /**
     * Gets the current {@link Root#_foci | focus} of a given type.
     */
    getFocus(focusType: FocusType): Widget | null;
    /**
     * Gets the last {@link Root#_fociCapturers | focus capturer} of a given
     * type.
     */
    getFocusCapturer(focusType: FocusType): Widget | null;
    /**
     * Registers a {@link Driver} to the root, adding it to the
     * {@link Root#drivers} list and calling {@link Driver#onEnable}. If the
     * driver was already registered, nothing happens.
     */
    registerDriver(driver: Driver): void;
    /**
     * Unregisters a {@link Driver} from the root, removing it from the
     * {@link Root#drivers} list and calling {@link Driver#onDisable}. If the
     * driver was not registered, nothing happens.
     */
    unregisterDriver(driver: Driver): void;
    /**
     * Unregisters all {@link Root#drivers} from the root, by calling
     * {@link Root#unregisterDriver}.
     */
    clearDrivers(): void;
    /**
     * Handle initialization of a text input handler. You probably don't need to
     * implement this method, unless you do something with the HTML elements
     * returned by the input handler (such as listening to focus or blur
     * events).
     */
    protected handleTextInputHandlerShow(_handler: TextInputHandler): void;
    /**
     * Dispose all resources associated with text input handler. You probably
     * don't need to implement this method, unless you do something with the
     * HTML elements returned by the input handler (such as listening to focus
     * or blur events).
     */
    protected handleTextInputHandlerDismiss(_handler: TextInputHandler): void;
    /**
     * Instantiate a text input handler. Used for mobile or WebXR where keyboard
     * events are hard to get. Note that this will replace the current handler
     * if there is any.
     *
     * @returns If {@link Root#textInputHandler} is set, returns a new instance, otherwise, returns null.
     */
    getTextInput(listener: TextInputHandlerListener, initialInput?: string, selectStart?: number, selectEnd?: number): TextInputHandler | null;
    /**
     * Shortcut for {@link Root#viewport}'s {@link CanvasViewport#resolution}
     * property.
     *
     * Note that, although the resolution is part of the {@link CanvasViewport}
     * API, widgets will treat the resolution property as being per-Root, not
     * per-Viewport (hence the lack of a Viewport.resolution property). The
     * resolution property is part of the CanvasViewport class so that
     * CanvasViewport is not circularly dependent on the Root class.
     */
    get resolution(): number;
    set resolution(resolution: number);
    /**
     * Shortcut for {@link Root#viewport}'s
     * {@link CanvasViewport#preventBleeding} property.
     */
    get preventBleeding(): boolean;
    set preventBleeding(preventBleeding: boolean);
    /**
     * Shortcut for {@link Root#viewport}'s
     * {@link CanvasViewport#preventAtlasBleeding} property.
     */
    get preventAtlasBleeding(): boolean;
    /**
     * Shortcut for {@link Root#viewport}'s
     * {@link CanvasViewport#maxCanvasWidth} property
     */
    get maxCanvasWidth(): number;
    set maxCanvasWidth(maxCanvasWidth: number);
    /**
     * Shortcut for {@link Root#viewport}'s
     * {@link CanvasViewport#maxCanvasHeight} property
     */
    get maxCanvasHeight(): number;
    set maxCanvasHeight(maxCanvasHeight: number);
    /**
     * Get the scale used for the {@link Root#viewport}. The horizontal and/or
     * vertical scale may not be 1 if {@link Root#maxCanvasWidth} or
     * {@link Root#maxCanvasHeight} are exceeded.
     *
     * Note that this is only valid after resolving {@link Root#child}'s layout.
     *
     * Equivalent to getting {@link Viewport#effectiveScale} on
     * {@link Root#viewport}.
     */
    get effectiveScale(): [scaleX: number, scaleY: number];
    /**
     * The root widget of this UI tree. Equivalent to getting
     * {@link Root#viewport}.{@link Viewport#child}.
     */
    get child(): Widget;
    /**
     * Destroy this Root. Disables the Root, clears all drivers, detaches the
     * {@link Root#child} Widget and resets {@link Root#textInputHandler}.
     *
     * Root must not be used after calling this method. Doing so will cause
     * exceptions to be thrown. There is no way to un-destroy a destroyed Root.
     *
     * Call this if you are no longer going to use this Root.
     */
    destroy(): void;
    /**
     * Listen to a specific event with a user listener. Chainable.
     *
     * Only events that pass through the Root will be listened; all trickling
     * events that start at the root will be listened, sticky events will only
     * be listened if they are dispatched at the Root, and bubbling events will
     * only be listened if none of the child widgets capture the event.
     *
     * @param eventType - The {@link WidgetEvent#"type"} to listen to
     * @param listener - The user-provided callback that will be invoked when the event is listened
     * @param once - Should the listener only be invoked once? False by default
     */
    on(eventType: string, listener: WidgetEventListener, once?: boolean): this;
    /**
     * Similar to {@link Root#on}, but any event type invokes the user-provided
     * callback, the listener can't be invoked only once, and the listener is
     * called with a lower priority than specific event listeners. Chainable.
     *
     * @param listener - The user-provided callback that will be invoked when a event is listened
     */
    onAny(listener: WidgetEventListener): this;
    /**
     * Remove an event listeners added with {@link Root#on}. Not chainable.
     *
     * @param eventType - The {@link WidgetEvent#"type"} to stop listening to
     * @param listener - The user-provided callback that was used in {@link Root#on}
     * @param once - Was the listener only meant to be invoked once? Must match what was used in {@link Root#on}
     */
    off(eventType: string, listener: WidgetEventListener, once?: boolean): boolean;
    /**
     * Remove an event listeners added with {@link Root#onAny}. Not chainable.
     *
     * @param listener - The user-provided callback that was used in {@link Root#onAny}
     */
    offAny(listener: WidgetEventListener): boolean;
    /**
     * Request that a specific ID is assigned to a specific {@link Widget} that
     * is attached to this Root. Must not be called manually; Widget will
     * automatically manage its ID when needed.
     *
     * @param id - The wanted ID
     * @param widget - The widget that the ID will be assigned to
     */
    requestID(id: string, widget: Widget): void;
    /**
     * Stop assigning a specific widget ID. Must not be called manually.
     *
     * @param id - The ID to stop assigning
     */
    dropID(id: string): void;
    /**
     * Get the widget that an ID is assigned to. If no widget is assigned to a
     * given ID, an error is thrown.
     *
     * @param id - The ID of the wanted {@link Widget}
     */
    getWidgetByID(id: string): Widget;
    /**
     * Mark a widget as hovered (received a pointer event since the last check).
     * Widgets will call this method automatically, there is no need to manually
     * call this.
     */
    markHovered(widget: Widget): void;
    private indexOfPointerStyle;
    /**
     * Request a pointer style. If the pointer style has a lower priority than
     * the current pointer style, it won't be displayed, but will still be
     * queued up in case the higher-priority style is cleared.
     */
    requestPointerStyle(widget: Widget, pointerStyle: string, source?: unknown): void;
    /**
     * Stop requesting a pointer style.
     */
    clearPointerStyle(widget: Widget, source?: unknown): void;
    /**
     * Stop requesting all pointer styles from a specific widget.
     */
    clearPointerStylesFromWidget(widget: Widget): void;
}
