import { EventEmitter } from "events";
import { type Node as YogaNode } from "./yoga.js";
import { OptimizedBuffer } from "./buffer.js";
import type { KeyEvent, PasteEvent } from "./lib/KeyHandler.js";
import type { Selection } from "./lib/selection.js";
import { type AlignString, type FlexDirectionString, type JustifyString, type OverflowString, type PositionTypeString, type WrapString } from "./lib/yoga.options.js";
import { type VNode } from "./renderables/composition/vnode.js";
import type { MouseEvent } from "./renderer.js";
import type { RenderContext } from "./types.js";
declare const BrandedRenderable: unique symbol;
export declare enum LayoutEvents {
    LAYOUT_CHANGED = "layout-changed",
    ADDED = "added",
    REMOVED = "removed",
    RESIZED = "resized"
}
export declare enum RenderableEvents {
    FOCUSED = "focused",
    BLURRED = "blurred",
    DESTROYED = "destroyed"
}
export interface Position {
    top?: number | "auto" | `${number}%`;
    right?: number | "auto" | `${number}%`;
    bottom?: number | "auto" | `${number}%`;
    left?: number | "auto" | `${number}%`;
}
export interface BaseRenderableOptions {
    id?: string;
}
export interface LayoutOptions extends BaseRenderableOptions {
    flexGrow?: number;
    flexShrink?: number;
    flexDirection?: FlexDirectionString;
    flexWrap?: WrapString;
    alignItems?: AlignString;
    justifyContent?: JustifyString;
    alignSelf?: AlignString;
    flexBasis?: number | "auto" | undefined;
    position?: PositionTypeString;
    overflow?: OverflowString;
    top?: number | "auto" | `${number}%`;
    right?: number | "auto" | `${number}%`;
    bottom?: number | "auto" | `${number}%`;
    left?: number | "auto" | `${number}%`;
    minWidth?: number | "auto" | `${number}%`;
    minHeight?: number | "auto" | `${number}%`;
    maxWidth?: number | "auto" | `${number}%`;
    maxHeight?: number | "auto" | `${number}%`;
    margin?: number | "auto" | `${number}%`;
    marginX?: number | "auto" | `${number}%`;
    marginY?: number | "auto" | `${number}%`;
    marginTop?: number | "auto" | `${number}%`;
    marginRight?: number | "auto" | `${number}%`;
    marginBottom?: number | "auto" | `${number}%`;
    marginLeft?: number | "auto" | `${number}%`;
    padding?: number | `${number}%`;
    paddingX?: number | `${number}%`;
    paddingY?: number | `${number}%`;
    paddingTop?: number | `${number}%`;
    paddingRight?: number | `${number}%`;
    paddingBottom?: number | `${number}%`;
    paddingLeft?: number | `${number}%`;
    enableLayout?: boolean;
}
export interface RenderableOptions<T extends BaseRenderable = BaseRenderable> extends Partial<LayoutOptions> {
    width?: number | "auto" | `${number}%`;
    height?: number | "auto" | `${number}%`;
    zIndex?: number;
    visible?: boolean;
    buffered?: boolean;
    live?: boolean;
    opacity?: number;
    renderBefore?: (this: T, buffer: OptimizedBuffer, deltaTime: number) => void;
    renderAfter?: (this: T, buffer: OptimizedBuffer, deltaTime: number) => void;
    onMouse?: (this: T, event: MouseEvent) => void;
    onMouseDown?: (this: T, event: MouseEvent) => void;
    onMouseUp?: (this: T, event: MouseEvent) => void;
    onMouseMove?: (this: T, event: MouseEvent) => void;
    onMouseDrag?: (this: T, event: MouseEvent) => void;
    onMouseDragEnd?: (this: T, event: MouseEvent) => void;
    onMouseDrop?: (this: T, event: MouseEvent) => void;
    onMouseOver?: (this: T, event: MouseEvent) => void;
    onMouseOut?: (this: T, event: MouseEvent) => void;
    onMouseScroll?: (this: T, event: MouseEvent) => void;
    onPaste?: (this: T, event: PasteEvent) => void;
    onKeyDown?: (key: KeyEvent) => void;
    onSizeChange?: (this: T) => void;
}
export declare function isRenderable(obj: any): obj is Renderable;
export declare abstract class BaseRenderable extends EventEmitter {
    [BrandedRenderable]: boolean;
    private static renderableNumber;
    protected _id: string;
    readonly num: number;
    protected _dirty: boolean;
    parent: BaseRenderable | null;
    protected _visible: boolean;
    constructor(options: BaseRenderableOptions);
    abstract add(obj: BaseRenderable | unknown, index?: number): number;
    abstract remove(id: string): void;
    abstract insertBefore(obj: BaseRenderable | unknown, anchor: BaseRenderable | unknown): void;
    abstract getChildren(): BaseRenderable[];
    abstract getChildrenCount(): number;
    abstract getRenderable(id: string): BaseRenderable | undefined;
    abstract requestRender(): void;
    abstract findDescendantById(id: string): BaseRenderable | undefined;
    get id(): string;
    set id(value: string);
    get isDirty(): boolean;
    protected markClean(): void;
    protected markDirty(): void;
    destroy(): void;
    destroyRecursively(): void;
    get visible(): boolean;
    set visible(value: boolean);
}
export declare abstract class Renderable extends BaseRenderable {
    static renderablesByNumber: Map<number, Renderable>;
    protected _isDestroyed: boolean;
    protected _ctx: RenderContext;
    protected _translateX: number;
    protected _translateY: number;
    protected _x: number;
    protected _y: number;
    protected _screenX: number;
    protected _screenY: number;
    protected _width: number | "auto" | `${number}%`;
    protected _height: number | "auto" | `${number}%`;
    protected _widthValue: number;
    protected _heightValue: number;
    private _zIndex;
    selectable: boolean;
    protected buffered: boolean;
    protected frameBuffer: OptimizedBuffer | null;
    protected _focusable: boolean;
    protected _focused: boolean;
    protected _hasFocusedDescendant: boolean;
    protected keypressHandler: ((key: KeyEvent) => void) | null;
    protected pasteHandler: ((event: PasteEvent) => void) | null;
    private _live;
    protected _liveCount: number;
    private _sizeChangeListener;
    private _mouseListener;
    private _mouseListeners;
    private _pasteListener;
    private _keyListeners;
    protected yogaNode: YogaNode;
    protected _positionType: PositionTypeString;
    protected _overflow: OverflowString;
    protected _position: Position;
    protected _opacity: number;
    private _flexShrink;
    private renderableMapById;
    protected _childrenInLayoutOrder: Renderable[];
    protected _childrenInZIndexOrder: Renderable[];
    private needsZIndexSort;
    parent: Renderable | null;
    private childrenPrimarySortDirty;
    private childrenSortedByPrimaryAxis;
    private _shouldUpdateBefore;
    private _lastLayoutFrame;
    onLifecyclePass: (() => void) | null;
    renderBefore?: (this: Renderable, buffer: OptimizedBuffer, deltaTime: number) => void;
    renderAfter?: (this: Renderable, buffer: OptimizedBuffer, deltaTime: number) => void;
    constructor(ctx: RenderContext, options: RenderableOptions<any>);
    get id(): string;
    set id(value: string);
    get focusable(): boolean;
    set focusable(value: boolean);
    get ctx(): RenderContext;
    get visible(): boolean;
    get primaryAxis(): "row" | "column";
    set visible(value: boolean);
    get opacity(): number;
    set opacity(value: number);
    hasSelection(): boolean;
    onSelectionChanged(selection: Selection | null): boolean;
    getSelectedText(): string;
    shouldStartSelection(x: number, y: number): boolean;
    focus(): void;
    protected propagateFocusChange(hasFocus: boolean): void;
    blur(): void;
    get focused(): boolean;
    get hasFocusedDescendant(): boolean;
    get live(): boolean;
    get liveCount(): number;
    set live(value: boolean);
    protected propagateLiveCount(delta: number): void;
    handleKeyPress?(key: KeyEvent): boolean;
    handlePaste?(event: PasteEvent): void;
    findDescendantById(id: string): Renderable | undefined;
    requestRender(): void;
    get translateX(): number;
    set translateX(value: number);
    get translateY(): number;
    set translateY(value: number);
    get screenX(): number;
    get screenY(): number;
    get x(): number;
    set x(value: number);
    get top(): number | "auto" | `${number}%` | undefined;
    set top(value: number | "auto" | `${number}%` | undefined);
    get right(): number | "auto" | `${number}%` | undefined;
    set right(value: number | "auto" | `${number}%` | undefined);
    get bottom(): number | "auto" | `${number}%` | undefined;
    set bottom(value: number | "auto" | `${number}%` | undefined);
    get left(): number | "auto" | `${number}%` | undefined;
    set left(value: number | "auto" | `${number}%` | undefined);
    get y(): number;
    set y(value: number);
    get width(): number;
    set width(value: number | "auto" | `${number}%`);
    get height(): number;
    set height(value: number | "auto" | `${number}%`);
    get zIndex(): number;
    set zIndex(value: number);
    private requestZIndexSort;
    private ensureZIndexSorted;
    getChildrenSortedByPrimaryAxis(): Renderable[];
    private setupYogaProperties;
    private setupMarginAndPadding;
    set position(positionType: PositionTypeString | null | undefined);
    get overflow(): OverflowString;
    set overflow(overflow: OverflowString | null | undefined);
    setPosition(position: Position): void;
    private updateYogaPosition;
    set flexGrow(grow: number | null | undefined);
    set flexShrink(shrink: number | null | undefined);
    set flexDirection(direction: FlexDirectionString | null | undefined);
    set flexWrap(wrap: WrapString | null | undefined);
    set alignItems(alignItems: AlignString | null | undefined);
    set justifyContent(justifyContent: JustifyString | null | undefined);
    set alignSelf(alignSelf: AlignString | null | undefined);
    set flexBasis(basis: number | "auto" | null | undefined);
    set minWidth(minWidth: number | `${number}%` | null | undefined);
    set maxWidth(maxWidth: number | `${number}%` | null | undefined);
    set minHeight(minHeight: number | `${number}%` | null | undefined);
    set maxHeight(maxHeight: number | `${number}%` | null | undefined);
    set margin(margin: number | "auto" | `${number}%` | null | undefined);
    set marginX(marginX: number | "auto" | `${number}%` | null | undefined);
    set marginY(marginY: number | "auto" | `${number}%` | null | undefined);
    set marginTop(margin: number | "auto" | `${number}%` | null | undefined);
    get marginTop(): number | "auto" | `${number}%`;
    set marginRight(margin: number | "auto" | `${number}%` | null | undefined);
    set marginBottom(margin: number | "auto" | `${number}%` | null | undefined);
    set marginLeft(margin: number | "auto" | `${number}%` | null | undefined);
    set padding(padding: number | `${number}%` | null | undefined);
    set paddingX(paddingX: number | `${number}%` | null | undefined);
    set paddingY(paddingY: number | `${number}%` | null | undefined);
    set paddingTop(padding: number | `${number}%` | null | undefined);
    set paddingRight(padding: number | `${number}%` | null | undefined);
    set paddingBottom(padding: number | `${number}%` | null | undefined);
    set paddingLeft(padding: number | `${number}%` | null | undefined);
    getLayoutNode(): YogaNode;
    updateFromLayout(): void;
    protected onLayoutResize(width: number, height: number): void;
    protected handleFrameBufferResize(width: number, height: number): void;
    protected createFrameBuffer(): void;
    /**
     * This will be called during a render pass.
     * Requesting a render during a render pass will drop the requested render.
     * If you need to request a render during a render pass, use process.nextTick.
     */
    protected onResize(width: number, height: number): void;
    private replaceParent;
    add(obj: Renderable | VNode<any, any[]> | unknown, index?: number): number;
    insertBefore(obj: Renderable | VNode<any, any[]> | unknown, anchor?: Renderable | unknown): number;
    getRenderable(id: string): Renderable | undefined;
    remove(id: string): void;
    protected onRemove(): void;
    getChildren(): Renderable[];
    getChildrenCount(): number;
    updateLayout(deltaTime: number, renderList?: RenderCommand[]): void;
    render(buffer: OptimizedBuffer, deltaTime: number): void;
    protected _hasVisibleChildFilter(): boolean;
    protected _getVisibleChildren(): number[];
    canReuseRenderCommandList(): boolean;
    protected onUpdate(deltaTime: number): void;
    protected getScissorRect(): {
        x: number;
        y: number;
        width: number;
        height: number;
    };
    protected renderSelf(buffer: OptimizedBuffer, deltaTime: number): void;
    get isDestroyed(): boolean;
    destroy(): void;
    destroyRecursively(): void;
    protected destroySelf(): void;
    processMouseEvent(event: MouseEvent): void;
    protected onMouseEvent(event: MouseEvent): void;
    set onMouse(handler: ((event: MouseEvent) => void) | undefined);
    set onMouseDown(handler: ((event: MouseEvent) => void) | undefined);
    set onMouseUp(handler: ((event: MouseEvent) => void) | undefined);
    set onMouseMove(handler: ((event: MouseEvent) => void) | undefined);
    set onMouseDrag(handler: ((event: MouseEvent) => void) | undefined);
    set onMouseDragEnd(handler: ((event: MouseEvent) => void) | undefined);
    set onMouseDrop(handler: ((event: MouseEvent) => void) | undefined);
    set onMouseOver(handler: ((event: MouseEvent) => void) | undefined);
    set onMouseOut(handler: ((event: MouseEvent) => void) | undefined);
    set onMouseScroll(handler: ((event: MouseEvent) => void) | undefined);
    set onPaste(handler: ((event: PasteEvent) => void) | undefined);
    get onPaste(): ((event: PasteEvent) => void) | undefined;
    set onKeyDown(handler: ((key: KeyEvent) => void) | undefined);
    get onKeyDown(): ((key: KeyEvent) => void) | undefined;
    set onSizeChange(handler: (() => void) | undefined);
    get onSizeChange(): (() => void) | undefined;
    private applyEventOptions;
}
interface RenderCommandBase {
    action: "render" | "pushScissorRect" | "popScissorRect" | "pushOpacity" | "popOpacity";
}
interface RenderCommandPushScissorRect extends RenderCommandBase {
    action: "pushScissorRect";
    x: number;
    y: number;
    width: number;
    height: number;
    screenX: number;
    screenY: number;
}
interface RenderCommandPopScissorRect extends RenderCommandBase {
    action: "popScissorRect";
}
interface RenderCommandRender extends RenderCommandBase {
    action: "render";
    renderable: Renderable;
}
interface RenderCommandPushOpacity extends RenderCommandBase {
    action: "pushOpacity";
    opacity: number;
}
interface RenderCommandPopOpacity extends RenderCommandBase {
    action: "popOpacity";
}
export type RenderCommand = RenderCommandPushScissorRect | RenderCommandPopScissorRect | RenderCommandRender | RenderCommandPushOpacity | RenderCommandPopOpacity;
export declare class RootRenderable extends Renderable {
    private renderList;
    private appliedLayoutGeneration;
    private appliedRenderListRevision;
    private renderListReusable;
    constructor(ctx: RenderContext);
    render(buffer: OptimizedBuffer, deltaTime: number): void;
    protected propagateLiveCount(delta: number): void;
    calculateLayout(): void;
    private syncExternalLayoutGeneration;
    private canReuseCurrentRenderList;
    resize(width: number, height: number): void;
}
export {};
