/**
 * UI / HUD Plugin for ECSpresso.
 *
 * Screen-space primitives:
 * - `uiElement` — anchor/pivot/offset positioning resolved against the `bounds` resource
 * - `uiLabel` — PixiJS Text
 * - `uiPanel` — PixiJS Graphics rectangle with optional border
 * - `uiProgressBar` — PixiJS Graphics value indicator with four fill directions
 *
 * Pointer interaction (buttons):
 * - `uiInteractive` (marker) opts an entity into hit-testing
 * - `uiInteraction.state` — `'none' | 'hover' | 'pressed'` (Bevy-style single enum)
 * - `uiButton` marker composes `uiInteractive` + `uiInteraction`
 * - `uiDisabled` skips hit-testing entirely
 * - Emits `uiButtonPressed` (confirmed down→up on same widget) and `uiButtonHovered`
 *
 * Depends on `renderer2D` (for the `bounds` resource + scene graph + screen-space layer),
 * the transform plugin (bundled by renderer2D), and the input plugin.
 *
 * Future phases will add the message log (Phase 3).
 */
import { type BasePluginOptions } from 'ecspresso';
import type { ComponentsConfig, ResourcesConfig } from '../../type-utils';
import type { Vector2D } from '../../utils/math';
import { type TransformComponentTypes } from '../spatial/transform';
import type { BoundsResourceTypes } from '../spatial/bounds';
import type { InputResourceTypes } from '../input/input';
export type AnchorPreset = 'top-left' | 'top-center' | 'top-right' | 'center-left' | 'center' | 'center-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
export declare const ANCHOR_PRESETS: Readonly<Record<AnchorPreset, Readonly<Vector2D>>>;
export type AnchorInput = AnchorPreset | Vector2D;
/** Resolve a preset string or vec2 into a mutable Vector2D copy. */
export declare function resolveAnchorPreset(input: AnchorInput): Vector2D;
/**
 * Write the top-left screen position of a widget into `out`.
 *
 * Formula: position = anchor * bounds + offset - pivot * size.
 * `anchor` specifies where on the canvas the widget attaches (0..1 normalized).
 * `pivot` specifies where on the widget that attachment point lands (0..1 normalized).
 * Writes in place to avoid per-frame allocation.
 */
export declare function resolveAnchorPosition(anchor: Readonly<Vector2D>, pivot: Readonly<Vector2D>, offset: Readonly<Vector2D>, bounds: Readonly<{
    width: number;
    height: number;
}>, size: Readonly<{
    width: number;
    height: number;
}>, out: Vector2D): void;
export type ProgressDirection = 'ltr' | 'rtl' | 'ttb' | 'btt';
export interface FillRect {
    x: number;
    y: number;
    width: number;
    height: number;
}
export declare function clampProgressValue(value: number, max: number): number;
export declare function computeProgressFillRect(width: number, height: number, ratio: number, direction: ProgressDirection, out: FillRect): void;
export interface UIElement {
    anchor: Vector2D;
    pivot: Vector2D;
    offset: Vector2D;
    width: number;
    height: number;
}
export interface UITextStyle {
    fontFamily: string;
    fontSize: number;
    fill: number;
    align: 'left' | 'center' | 'right';
}
export interface UILabel {
    text: string;
    style: UITextStyle;
}
export interface UIPanel {
    fillColor: number;
    borderColor?: number;
    borderWidth: number;
}
export interface UIProgressBar {
    value: number;
    max: number;
    fillColor: number;
    bgColor: number;
    direction: ProgressDirection;
}
export type UIInteractionState = 'none' | 'hover' | 'pressed';
export interface UIInteraction {
    state: UIInteractionState;
}
export interface LogFragment {
    text: string;
    color: number;
}
export interface UIMessageLog {
    lines: LogFragment[][];
    maxLines: number;
    visibleLines: number;
    lineHeight: number;
    style: UITextStyle;
}
export interface UIComponentTypes {
    uiElement: UIElement;
    uiLabel: UILabel;
    uiPanel: UIPanel;
    uiProgressBar: UIProgressBar;
    uiButton: {};
    uiInteractive: {};
    uiInteraction: UIInteraction;
    uiDisabled: {};
    uiMessageLog: UIMessageLog;
}
export interface UIButtonPressedEvent {
    entityId: number;
}
export interface UIButtonHoveredEvent {
    entityId: number;
    entered: boolean;
}
export interface UIMessageLogAppendedEvent {
    entityId: number;
    line: LogFragment[];
}
export interface UIEventTypes {
    uiButtonPressed: UIButtonPressedEvent;
    uiButtonHovered: UIButtonHoveredEvent;
    uiLogAppended: UIMessageLogAppendedEvent;
}
export interface CreateUIElementInput {
    anchor: AnchorInput;
    pivot?: AnchorInput;
    offset?: Vector2D;
    width: number;
    height: number;
}
export declare function createUIElement(input: CreateUIElementInput): Pick<UIComponentTypes, 'uiElement'>;
export declare function createUILabel(text: string, style?: Partial<UITextStyle>): Pick<UIComponentTypes, 'uiLabel'>;
export interface CreateUIPanelInput {
    fillColor: number;
    borderColor?: number;
    borderWidth?: number;
}
export declare function createUIPanel(input: CreateUIPanelInput): Pick<UIComponentTypes, 'uiPanel'>;
export interface CreateUIProgressBarInput {
    value: number;
    max: number;
    fillColor: number;
    bgColor: number;
    direction?: ProgressDirection;
}
export declare function createUIProgressBar(input: CreateUIProgressBarInput): Pick<UIComponentTypes, 'uiProgressBar'>;
export interface CreateUIMessageLogInput {
    maxLines: number;
    visibleLines: number;
    lineHeight: number;
    style?: Partial<UITextStyle>;
    initialLines?: LogFragment[][];
}
export declare function createUIMessageLog(input: CreateUIMessageLogInput): Pick<UIComponentTypes, 'uiMessageLog'>;
export declare function createUIInteractive(): Pick<UIComponentTypes, 'uiInteractive'>;
export declare function createUIButton(): Pick<UIComponentTypes, 'uiButton'>;
export declare function createUIDisabled(): Pick<UIComponentTypes, 'uiDisabled'>;
/** Structural ECS surface for `appendLogLine`; mirrors the `CoroutineWorld` pattern. */
export interface MessageLogWorld {
    commands: {
        mutateComponent(entityId: number, componentName: 'uiMessageLog', mutator: (value: UIMessageLog) => void): void;
    };
    eventBus: {
        publish(event: 'uiLogAppended', payload: UIMessageLogAppendedEvent): void;
    };
}
/**
 * Append a line (vector of fragments) to a `uiMessageLog` entity.
 *
 * Queues a buffered mutation that swaps `lines` for a fresh array (FIFO-truncated to
 * `maxLines`) — the array-identity change is the sync system's redraw signal — and
 * synchronously publishes `uiLogAppended` carrying the line for entry-animation
 * listeners. Safe to call from inside a system process callback.
 */
export declare function appendLogLine(ecs: MessageLogWorld, entityId: number, line: LogFragment[]): void;
type UIRequires = ComponentsConfig<TransformComponentTypes> & ResourcesConfig<BoundsResourceTypes & InputResourceTypes>;
type UILabels = 'ui-anchor-resolve' | 'ui-interaction' | 'ui-label-sync' | 'ui-panel-sync' | 'ui-progress-sync' | 'ui-message-log-sync';
export interface UIPluginOptions<G extends string = 'ui'> extends BasePluginOptions<G> {
    /** Priority for the anchor-resolve system in preUpdate (default: 0). */
    anchorPriority?: number;
    /** Priority for the pointer hit-test system in preUpdate (default: 200, after input's 100). */
    interactionPriority?: number;
    /** Priority for render-sync systems (default: 480, just before renderer2D's 500). */
    renderSyncPriority?: number;
}
export declare function createUIPlugin<G extends string = 'ui'>(options?: UIPluginOptions<G>): import("ecspresso").Plugin<import("ecspresso").WithEvents<import("ecspresso").WithComponents<import("ecspresso").EmptyConfig, UIComponentTypes>, UIEventTypes>, UIRequires, UILabels, G, never, "ui-labels" | "ui-panels" | "ui-progress-bars" | "ui-message-logs">;
export {};
