/**
 * useUISlots Hook
 *
 * Core hook for managing UI slot rendering in the trait-driven architecture.
 * Traits use render_ui effects to dynamically render content into slots.
 *
 * Slots:
 * - main: Primary content area
 * - sidebar: Left/right sidebar
 * - modal: Modal overlay
 * - drawer: Slide-in drawer
 * - overlay: Full-screen overlay
 * - center: Centered popup
 * - toast: Toast notifications
 * - hud-top: Game HUD top bar
 * - hud-bottom: Game HUD bottom bar
 * - floating: Draggable floating panel
 *
 * Multi-source model (2026-04-24):
 * A slot can receive renders from multiple source traits across independent
 * batches (e.g. in the playground, ProbeCreate renders "main" on INIT, then
 * later ProbePersistor cascades a render into "main" too). Prior code stored
 * a single SlotContent per slot and last-writer-wins silently dropped
 * earlier traits' frames. Internally the manager now holds a
 * `Record<UISlot, Record<sourceKey, SlotContent>>` map and consumers see an
 * aggregated view: a single SlotContent for single-source slots, or a
 * synthetic `stack` wrapper when 2+ sources are active simultaneously.
 * This mirrors the compiled-path page layout's VStack-of-trait-views.
 *
 * @packageDocumentation
 */
import type React from 'react';
import type { EventPayloadValue, RenderItemLambda } from '@almadar/core';
/**
 * Valid UI slot names
 */
export type UISlot = 'main' | 'sidebar' | 'modal' | 'drawer' | 'overlay' | 'center' | 'toast' | 'hud-top' | 'hud-bottom' | 'hud-left' | 'hud-right' | 'floating';
/**
 * Animation types for slot transitions
 */
export type SlotAnimation = 'fade' | 'slide' | 'scale' | 'none';
/**
 * Render-prop callback after fn-form-lambda conversion or
 * `wrapCallbackForEvent` wrapping. Pattern components consume these as
 * `renderItem` / `onTabChange` / `onClick` / etc. The arg list is
 * contravariant (`never[]` accepts any caller shape — event handlers,
 * 2-arg `(item, index)` render-props, etc.); the return is the union of
 * shapes seen at this layer. Pattern-level prop types narrow the
 * signature for each consumer downstream.
 */
export type SlotCallback = (...args: never[]) => void | React.ReactNode | EventPayloadValue;
/**
 * Render-ui prop value: any leaf flowing from a `(render-ui slot {...})`
 * effect into a React pattern component. The union enumerates every
 * shape the renderer can receive — no `unknown` escape hatch.
 *
 * - JSON primitives (`string`, `number`, `boolean`, `Date`, `null`,
 *   `undefined`) come through `BindingResolver`.
 * - `RenderItemLambda` is the unconverted tuple form `["fn", arg, body]`;
 *   `SlotCallback` is the post-conversion callable form.
 * - `React.ReactNode` covers substituted `<TraitFrame>` elements.
 * - The recursive array + object branches mirror the `EventPayloadValue`
 *   shape but with `SlotPropValue` leaves so functions and React nodes
 *   can appear at any depth (e.g. `tabs[].content: "@trait.X"` surviving
 *   substitution into a `ReactElement`).
 */
export type SlotPropValue = string | number | boolean | Date | null | undefined | RenderItemLambda | SlotCallback | React.ReactElement | ReadonlyArray<SlotPropValue> | {
    readonly [key: string]: SlotPropValue;
};
/**
 * Pattern-specific props carried by a rendered slot. The slot manager
 * routes these from `(render-ui slot {...})` effects to React pattern
 * components without coercion.
 */
export type SlotProps = Record<string, SlotPropValue>;
/**
 * Content rendered in a slot
 */
export interface SlotContent {
    /** Unique ID for this content */
    id: string;
    /** Pattern/component type to render */
    pattern: string;
    /** Props to pass to the pattern component */
    props: SlotProps;
    /** Priority for conflict resolution (higher wins) */
    priority: number;
    /** Animation for showing/hiding */
    animation?: SlotAnimation;
    /** Auto-dismiss timestamp (for toasts) */
    autoDismissAt?: number;
    /** Callback when dismissed */
    onDismiss?: () => void;
    /** Source trait that rendered this content */
    sourceTrait?: string;
    /** Stable node ID from the schema pattern tree (for edit mode overlay targeting) */
    nodeId?: string;
}
/**
 * Configuration for render_ui effect
 */
export interface RenderUIConfig {
    /** Target slot */
    target: UISlot;
    /** Pattern/component to render */
    pattern: string;
    /** Props for the pattern */
    props?: SlotProps;
    /** Priority (default: 0) */
    priority?: number;
    /** Animation type */
    animation?: SlotAnimation;
    /** Auto-dismiss after ms (for toasts) */
    autoDismissMs?: number;
    /** Callback on dismiss */
    onDismiss?: () => void;
    /** Source trait name */
    sourceTrait?: string;
}
/**
 * Callback for slot changes
 */
export type SlotChangeCallback = (slot: UISlot, content: SlotContent | null) => void;
/**
 * Fires when a specific trait's current render-ui output changes.
 * Used by `<TraitFrame>` to subscribe only to the trait it embeds,
 * avoiding wide re-renders when unrelated slots update.
 *
 * Per-trait index stores exactly one entry per trait (the most recent
 * render), so the callback signature carries just the new content —
 * no per-slot disambiguation needed.
 */
export type TraitChangeCallback = (content: SlotContent | null) => void;
/**
 * UI Slot Manager interface
 */
export interface UISlotManager {
    /**
     * Current aggregate content for each slot. Single-source slots hold
     * that source's SlotContent; multi-source slots hold a synthetic
     * `stack` wrapper whose `children` prop is the list of per-source
     * pattern configs in insertion order. Single consumers can continue
     * to read `slots[slot]` without knowing the slot is multi-source.
     */
    slots: Record<UISlot, SlotContent | null>;
    /** Render content to a slot */
    render: (config: RenderUIConfig) => string;
    /** Clear all source entries from a slot */
    clear: (slot: UISlot) => void;
    /** Clear a single source's contribution from a slot, keeping others */
    clearBySource: (slot: UISlot, sourceTrait: string) => void;
    /** Clear content by ID */
    clearById: (id: string) => void;
    /** Clear all slots */
    clearAll: () => void;
    /** Subscribe to slot changes */
    subscribe: (callback: SlotChangeCallback) => () => void;
    /** Check if a slot has content */
    hasContent: (slot: UISlot) => boolean;
    /** Get aggregated content for a slot (single or synthetic stack) */
    getContent: (slot: UISlot) => SlotContent | null;
    /**
     * Look up the most recent `render-ui` output a given trait produced,
     * keyed by `SlotContent.sourceTrait`. Returns `null` when the trait
     * hasn't rendered yet.
     *
     * Backs the `@trait.X` binding's client-side resolution via
     * `<TraitFrame>`. See `docs/Almadar_Std_Gaps.md` §3.8. The binding is
     * single-segment — there's intentionally no slot disambiguation.
     */
    getTraitContent: (traitName: string) => SlotContent | null;
    /**
     * Subscribe to changes in a specific trait's render output. Returns
     * an unsubscribe function.
     *
     * Scoped per-trait so `<TraitFrame>` components only re-render when
     * the trait they embed actually changes — not on every slot update.
     */
    subscribeTrait: (traitName: string, callback: TraitChangeCallback) => () => void;
    /**
     * Update only the per-trait sidecar without writing to any slot.
     *
     * Used for embed-aware slot routing: when a trait is referenced via
     * `@trait.X` by a sibling layout's render-ui, its render output should
     * not stack into the same slot the layout writes — the layout owns the
     * slot and embeds the trait's frame via `<TraitFrame>`. This method
     * keeps the per-trait sidecar (`traitIndexRef`) up-to-date so
     * `<TraitFrame>` re-renders, while leaving `slots[target]` untouched.
     *
     * Mirrors what the compiled-path codegen does structurally — atoms
     * inlined as JSX inside the layout's pattern, not writing slots.
     */
    updateTraitContent: (traitName: string, content: Omit<SlotContent, 'id' | 'sourceTrait'>) => string;
}
declare const DEFAULT_SLOTS: Record<UISlot, SlotContent | null>;
/**
 * Create a UI Slot Manager instance.
 *
 * This is the internal hook that creates the manager.
 * Use `useUISlots()` from context in components.
 */
export declare function useUISlotManager(): UISlotManager;
export { DEFAULT_SLOTS };
