tui-lipan 0.1.0

Opinionated, component-based TUI framework for Rust - declarative components, reconciliation, layout engine, focus, overlays, and rich widgets on top of ratatui.
Documentation
use std::sync::Arc;

use crate::callback::Callback;
use crate::core::node::{NodeKind, WidgetNode};
use crate::style::{StyleSlot, Theme, ThemeRole};

use super::drop_target::{DropHighlight, DropTarget, PayloadAcceptFn};
use super::payload::{DragLeaveEvent, DragOverEvent, DropEvent, DropSlot};

#[derive(Clone)]
pub struct DropTargetNode {
    pub on_drag_over: Option<Callback<DragOverEvent>>,
    pub on_drag_leave: Option<Callback<DragLeaveEvent>>,
    pub on_drop: Option<Callback<DropEvent>>,
    pub accept_group: Option<Arc<str>>,
    pub can_accept: Option<PayloadAcceptFn>,
    pub highlight: DropHighlight,
    pub highlight_style: StyleSlot,
    pub drop_slot: DropSlot,
    pub enabled: bool,
    pub dnd_highlighted: bool,
}

impl Default for DropTargetNode {
    fn default() -> Self {
        Self {
            on_drag_over: None,
            on_drag_leave: None,
            on_drop: None,
            accept_group: None,
            can_accept: None,
            highlight: DropHighlight::None,
            highlight_style: StyleSlot::Inherit,
            drop_slot: DropSlot::Child,
            enabled: true,
            dnd_highlighted: false,
        }
    }
}

impl WidgetNode for DropTargetNode {
    fn has_on_click(&self) -> bool {
        self.enabled
            && (self.on_drop.is_some()
                || self.on_drag_over.is_some()
                || (self.highlight != DropHighlight::None
                    && !matches!(self.highlight_style, StyleSlot::Inherit)))
    }

    fn is_hoverable_for_theme(&self, theme: &Theme) -> bool {
        self.enabled
            && (self.on_drag_over.is_some()
                || (self.highlight != DropHighlight::None
                    && self
                        .highlight_style
                        .resolves_non_empty(theme, ThemeRole::DropTargetActive)))
    }
}

impl From<DropTarget> for DropTargetNode {
    fn from(value: DropTarget) -> Self {
        Self {
            on_drag_over: value.on_drag_over,
            on_drag_leave: value.on_drag_leave,
            on_drop: value.on_drop,
            accept_group: value.accept_group,
            can_accept: value.can_accept,
            highlight: value.highlight,
            highlight_style: value.highlight_style,
            drop_slot: value.drop_slot,
            enabled: value.enabled,
            dnd_highlighted: false,
        }
    }
}

impl From<DropTargetNode> for NodeKind {
    fn from(node: DropTargetNode) -> Self {
        NodeKind::DropTarget(node)
    }
}