aura-gui 0.3.5

UI nativa acelerada por GPU para escritorio, Android e iOS, en un solo crate: estilo tipo Tailwind, componentes, sombras, animaciones y agentes de IA. Reposo a cero. Licencia AGPL-3.0 o comercial.
//! Métodos de construcción de `Div`: estados, eventos de ratón y teclado, foco.

use crate::core::{Action, FocusHandle};
use crate::view::div::Div;
use crate::view::interactivity::{
    ActionEvent, ClickEvent, DragEvent, EventContext, KeyDownEvent, ScrollEvent, TextInputEvent,
};
use crate::view::key_context::KeyContext;
use crate::view::style::Style;
use std::rc::Rc;

impl Div {
    /// Identificador estable; necesario para conservar el scroll entre frames.
    pub fn id(mut self, id: impl Into<String>) -> Self {
        self.interactivity.id = Some(id.into());
        self
    }

    pub fn hover(mut self, refine: impl FnOnce(Style) -> Style) -> Self {
        self.interactivity.hover_style = Some(refine(Style::default()));
        self
    }

    pub fn active(mut self, refine: impl FnOnce(Style) -> Style) -> Self {
        self.interactivity.active_style = Some(refine(Style::default()));
        self
    }

    /// Estilo extra mientras este elemento tiene el foco (`track_focus`).
    pub fn focus(mut self, refine: impl FnOnce(Style) -> Style) -> Self {
        self.interactivity.focus_style = Some(refine(Style::default()));
        self
    }

    pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut EventContext) + 'static) -> Self {
        self.interactivity.on_click = Some(Rc::new(handler));
        self
    }

    pub fn on_mouse_down(mut self, handler: impl Fn(&ClickEvent, &mut EventContext) + 'static) -> Self {
        self.interactivity.on_mouse_down = Some(Rc::new(handler));
        self
    }

    /// Clic secundario: el lugar natural para abrir un menú contextual.
    pub fn on_right_click(mut self, handler: impl Fn(&ClickEvent, &mut EventContext) + 'static) -> Self {
        self.interactivity.on_right_click = Some(Rc::new(handler));
        self
    }

    pub fn on_scroll(mut self, handler: impl Fn(&ScrollEvent, &mut EventContext) + 'static) -> Self {
        self.interactivity.on_scroll = Some(Rc::new(handler));
        self
    }

    /// Se invoca en cada movimiento del ratón mientras este elemento está presionado.
    pub fn on_drag(mut self, handler: impl Fn(&DragEvent, &mut EventContext) + 'static) -> Self {
        self.interactivity.on_drag = Some(Rc::new(handler));
        self
    }

    /// Movimiento del ratón sobre el elemento sin botones presionados (hover con retardo).
    pub fn on_mouse_move(mut self, handler: impl Fn(&DragEvent, &mut EventContext) + 'static) -> Self {
        self.interactivity.on_mouse_move = Some(Rc::new(handler));
        self
    }

    /// Guarda en `cell` el rectángulo del elemento en cada frame (para cálculos de arrastre).
    pub fn record_bounds(mut self, cell: Rc<std::cell::Cell<crate::core::Bounds>>) -> Self {
        self.interactivity.record_bounds = Some(cell);
        self
    }

    /// Texto que aparece tras unos instantes con el puntero encima.
    pub fn tooltip(mut self, text: impl Into<String>) -> Self {
        let text: String = text.into();
        self.interactivity.tooltip = Some(Rc::from(text));
        self
    }

    /// Hace el elemento enfocable: recibe teclado cuando su `FocusHandle` tiene el foco.
    pub fn track_focus(mut self, handle: &FocusHandle) -> Self {
        self.interactivity.focus = Some(*handle);
        self
    }

    /// Posición en el recorrido con Tab (requiere `track_focus`).
    pub fn tab_index(mut self, index: i32) -> Self {
        self.interactivity.tab_index = Some(index);
        self
    }

    /// Contexto para el keymap: `"Editor"`, `"Picker"`, `"Terminal"`...
    pub fn key_context(mut self, context: &str) -> Self {
        self.interactivity.key_context = Some(KeyContext::parse(context));
        self
    }

    /// Maneja una acción cuando la ruta de foco pasa por este elemento.
    pub fn on_action(mut self, action: Action, handler: impl Fn(&ActionEvent, &mut EventContext) + 'static) -> Self {
        self.interactivity.actions.push((action, Rc::new(handler)));
        self
    }

    /// Teclas que ningún atajo consumió (la terminal las convierte en bytes).
    pub fn on_key_down(mut self, handler: impl Fn(&KeyDownEvent, &mut EventContext) + 'static) -> Self {
        self.interactivity.on_key_down = Some(Rc::new(handler));
        self
    }

    /// Texto escrito y composición IME.
    pub fn on_text_input(mut self, handler: impl Fn(&TextInputEvent, &mut EventContext) + 'static) -> Self {
        self.interactivity.on_text_input = Some(Rc::new(handler));
        self
    }

    /// Aplica encima un estilo parcial; lo usan los widgets para respetar ajustes del usuario.
    pub fn refine_style(mut self, style: &Style) -> Self {
        self.style.refine(style);
        self
    }

    /// Impide que el ratón llegue a los elementos que quedan debajo (modales, paletas).
    pub fn occlude(mut self) -> Self {
        self.interactivity.blocks_mouse = true;
        self
    }

    pub fn when(self, condition: bool, build: impl FnOnce(Self) -> Self) -> Self {
        if condition { build(self) } else { self }
    }

    pub fn when_some<T>(self, value: Option<T>, build: impl FnOnce(Self, T) -> Self) -> Self {
        match value {
            Some(value) => build(self, value),
            None => self,
        }
    }
}