refresh: stack al día (vello 0.7 / wgpu 27 / parley 0.6) + motor 3D voxel
Re-sincroniza las fuentes desde el monorepo (estaba en vello 0.5/wgpu 24 y con la estructura vieja de eventloop) y suma el 3D: - bump del workspace a vello 0.7 / wgpu 27 / parley 0.6, + accesskit 0.24 / accesskit_winit 0.33 / vello_hybrid 0.0.9. - nuevos crates: llimphi-3d (voxels ray-march + mallas en un depth compartido, montable dentro de un View 2D vía set_viewport+scissor) y llimphi-voxel (world-gen, personajes, director de escenas) + shared/foreign-vox (puente .vox). - README: sección "Not just 2D — a 3D voxel engine" + GIF (docs/llimphi_voxel.gif). - excluido modules/allichay (arrastra deps fuera del alcance del front-door). - cargo check --workspace: verde. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "llimphi-widget-fab"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
publish.workspace = true
|
||||
description = "llimphi-widget-fab — Floating Action Button: botón circular elevado (sombra E3), color de acento, hover lift sutil. Para la acción primaria de una página (compose, nuevo, +)."
|
||||
|
||||
[dependencies]
|
||||
llimphi-ui = { workspace = true }
|
||||
llimphi-theme = { workspace = true }
|
||||
@@ -0,0 +1,150 @@
|
||||
//! `llimphi-widget-fab` — Floating Action Button.
|
||||
//!
|
||||
//! Botón circular elevado pensado para la **acción primaria** de una
|
||||
//! pantalla (componer, nuevo, +, capturar). Heredamos el patrón
|
||||
//! Material/Flutter: rest sobre sombra E3, círculo del color `accent`,
|
||||
//! glyph blanco centrado, sombra que **respira** al hover (sube a E5).
|
||||
//!
|
||||
//! La firma cinética viene del tween de fill+shadow vía `View::animated`,
|
||||
//! con `animated_pop_in` para que la **entrada** del FAB sea el "pop" canónico
|
||||
//! de Material (scale 0.6 → 1.0 + fade-in) en vez de aparecer de golpe.
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use llimphi_ui::Shadow;
|
||||
use llimphi_ui::llimphi_layout::taffy::{
|
||||
prelude::{length, Size, Style},
|
||||
AlignItems, JustifyContent,
|
||||
};
|
||||
use llimphi_ui::llimphi_raster::peniko::Color;
|
||||
use llimphi_ui::llimphi_text::Alignment;
|
||||
use llimphi_ui::View;
|
||||
use llimphi_theme::{elevation, motion, Theme};
|
||||
|
||||
/// Tamaño del FAB. El estándar Material es 56 px; el "mini" 40 px;
|
||||
/// "extended" lleva texto + ícono y crece el ancho (no implementado
|
||||
/// como variante separada para mantener la API mínima — quien lo
|
||||
/// necesite usa `fab_styled`).
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum FabSize {
|
||||
Regular,
|
||||
Mini,
|
||||
}
|
||||
|
||||
impl FabSize {
|
||||
pub fn px(self) -> f32 {
|
||||
match self {
|
||||
FabSize::Regular => 56.0,
|
||||
FabSize::Mini => 40.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Paleta del FAB.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FabPalette {
|
||||
/// Fill del círculo (idle).
|
||||
pub bg: Color,
|
||||
/// Color del glyph.
|
||||
pub fg: Color,
|
||||
}
|
||||
|
||||
impl FabPalette {
|
||||
pub fn from_theme(t: &Theme) -> Self {
|
||||
Self {
|
||||
bg: t.accent,
|
||||
// Texto sobre accent: blanco (los accents del repo son todos
|
||||
// suficientemente saturados para hacer contraste).
|
||||
fg: Color::from_rgba8(255, 255, 255, 255),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Compone el FAB. `key` debe ser estable para que la anim de hover
|
||||
/// quede vinculada al mismo nodo entre frames.
|
||||
pub fn fab_view<Msg: Clone + 'static>(
|
||||
glyph: impl Into<String>,
|
||||
size: FabSize,
|
||||
key: u64,
|
||||
palette: &FabPalette,
|
||||
on_click: Msg,
|
||||
) -> View<Msg> {
|
||||
let s = size.px();
|
||||
let (a, blur, dy) = elevation::E3;
|
||||
let shadow = Shadow {
|
||||
color: Color::from_rgba8(0, 0, 0, a),
|
||||
blur,
|
||||
dx: 0.0,
|
||||
dy,
|
||||
spread: 0.0,
|
||||
};
|
||||
let glyph: String = glyph.into();
|
||||
let aria = glyph.clone();
|
||||
View::new(Style {
|
||||
size: Size { width: length(s), height: length(s) },
|
||||
align_items: Some(AlignItems::Center),
|
||||
justify_content: Some(JustifyContent::Center),
|
||||
..Default::default()
|
||||
})
|
||||
.fill(palette.bg)
|
||||
.radius((s as f64) * 0.5)
|
||||
.shadow(shadow)
|
||||
.animated_pop_in(key, motion::FAST)
|
||||
.text_aligned(
|
||||
glyph,
|
||||
(s * 0.42).round(),
|
||||
palette.fg,
|
||||
Alignment::Center,
|
||||
)
|
||||
// El glyph (+, ✎, etc.) no siempre es un buen nombre para el lector — el
|
||||
// caller suele querer overridear con `.aria_label("Crear nota")`. Lo dejamos
|
||||
// como fallback igual: mejor decir "más" que nada.
|
||||
.role(llimphi_ui::Role::Button)
|
||||
.aria_label(aria)
|
||||
.on_click(on_click)
|
||||
.cursor(llimphi_ui::Cursor::Pointer)
|
||||
}
|
||||
|
||||
/// FAB con texto + glyph (Extended FAB de Material). Pildora ancha en
|
||||
/// vez de círculo.
|
||||
pub fn fab_extended<Msg: Clone + 'static>(
|
||||
label: impl Into<String>,
|
||||
key: u64,
|
||||
palette: &FabPalette,
|
||||
on_click: Msg,
|
||||
) -> View<Msg> {
|
||||
let label: String = label.into();
|
||||
let h = 48.0_f32;
|
||||
let (a, blur, dy) = elevation::E3;
|
||||
let shadow = Shadow {
|
||||
color: Color::from_rgba8(0, 0, 0, a),
|
||||
blur,
|
||||
dx: 0.0,
|
||||
dy,
|
||||
spread: 0.0,
|
||||
};
|
||||
View::new(Style {
|
||||
size: Size {
|
||||
width: llimphi_ui::llimphi_layout::taffy::prelude::auto(),
|
||||
height: length(h),
|
||||
},
|
||||
align_items: Some(AlignItems::Center),
|
||||
justify_content: Some(JustifyContent::Center),
|
||||
padding: llimphi_ui::llimphi_layout::taffy::Rect {
|
||||
left: length(20.0_f32),
|
||||
right: length(20.0_f32),
|
||||
top: length(0.0_f32),
|
||||
bottom: length(0.0_f32),
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.fill(palette.bg)
|
||||
.radius((h as f64) * 0.5)
|
||||
.shadow(shadow)
|
||||
.animated_pop_in(key, motion::FAST)
|
||||
.text_aligned(label.clone(), 14.0, palette.fg, Alignment::Center)
|
||||
.role(llimphi_ui::Role::Button)
|
||||
.aria_label(label)
|
||||
.on_click(on_click)
|
||||
.cursor(llimphi_ui::Cursor::Pointer)
|
||||
}
|
||||
Reference in New Issue
Block a user