feat: llimphi standalone — framework UI soberano extraído del monorepo

Motor gráfico Llimphi como workspace independiente: bucle Elm
(input→update→view→layout→raster→present) sobre wgpu+vello+taffy+parley.
Núcleo (hal/raster/layout/text/ui/theme/surface/motion/icons) + ~40 widgets
+ módulos, sin dependencias al resto del monorepo. cargo check --workspace
pasa (64 crates). Puerta de entrada: cargo run -p llimphi-ui --example counter.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-04 04:23:42 +00:00
commit e65e9cc623
286 changed files with 46136 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
[package]
name = "llimphi-clipboard"
version.workspace = true
edition.workspace = true
license.workspace = true
authors.workspace = true
publish.workspace = true
description = "llimphi-clipboard — backend de portapapeles del sistema (vía arboard) que implementa el trait Clipboard del text-editor. Una línea para que el menú de edición y los atajos Ctrl+C/X/V de cualquier app Llimphi usen el clipboard real del SO, con degradación silenciosa a no-op si no hay display."
[dependencies]
llimphi-widget-text-editor = { workspace = true }
arboard = { workspace = true }
+55
View File
@@ -0,0 +1,55 @@
//! `llimphi-clipboard` — el portapapeles del sistema para apps Llimphi.
//!
//! El `text-editor` define el trait [`Clipboard`] pero deja el backend al
//! caller (no quiere acoplarse a X11/Wayland/macOS/Windows). Este crate
//! aporta el backend obvio — [`arboard`] — para que cualquier app lo
//! enchufe en una línea:
//!
//! ```ignore
//! let mut clip = llimphi_clipboard::SystemClipboard::new();
//! editor.apply_key_with_clipboard(&ev, &mut clip);
//! ```
//!
//! Si no hay display (CI headless, sesión sin servidor gráfico) degrada
//! a no-op silencioso: `get` devuelve `None`, `set` descarta. Nunca
//! panica.
#![forbid(unsafe_code)]
use llimphi_widget_text_editor::Clipboard;
/// Portapapeles del sistema vía `arboard`. `None` interno = no se pudo
/// abrir (sin display); en ese caso opera como [`llimphi_widget_text_editor::NullClipboard`].
pub struct SystemClipboard {
inner: Option<arboard::Clipboard>,
}
impl SystemClipboard {
pub fn new() -> Self {
Self {
inner: arboard::Clipboard::new().ok(),
}
}
/// `true` si el backend del SO está disponible.
pub fn is_available(&self) -> bool {
self.inner.is_some()
}
}
impl Default for SystemClipboard {
fn default() -> Self {
Self::new()
}
}
impl Clipboard for SystemClipboard {
fn get(&mut self) -> Option<String> {
self.inner.as_mut()?.get_text().ok()
}
fn set(&mut self, s: &str) {
if let Some(c) = self.inner.as_mut() {
let _ = c.set_text(s.to_owned());
}
}
}