1# llimphi-widget-scroll
2
3*Read this in English: [README.md](README.md).*
4
5Área de scroll vertical reutilizable.
6
7Hasta ahora cada app rearmaba el scroll a mano: `App::on_wheel` + un
8offset en el `Model` + `clip` + virtualización. Este widget empaqueta
9ese patrón en un solo builder, **sin estado propio** (el offset sigue
10viviendo en el `Model`, fiel al bucle Elm):
11
12- **viewport clipeado** de alto fijo (`viewport_len`),
13- **contenido desplazado** `-offset` px (overflow recortado),
14- **barra de scroll arrastrable** a la derecha (sólo si el contenido
15 excede el viewport),
16- **rueda autocontenida** vía `View::on_scroll`: girar la rueda con
17 el cursor sobre el área emite un `Msg` sin que la app rutee nada por
18 su `on_wheel` global.
19
20El caller debe conocer el **alto total del contenido** (`content_len`)
21y el **alto visible** (`viewport_len`) — igual que `list`/`grid` ya
22piden la ventana visible. Para contenido de filas uniformes es
23`n_filas * alto_fila`.
24
25## Convención del callback `on_scroll`
26
27`on_scroll` recibe el **delta en px** a sumar al offset (no el offset
28absoluto): tanto la rueda como el arrastre de la barra emiten deltas,
29y el caller acumula + clampea en su `update` con `clamp_offset`. Es
30la misma idea que el `splitter` (el handler de drag se reusa durante
31todo el arrastre, así que un offset absoluto capturado se quedaría
32viejo; el delta-por-evento siempre es correcto).
33```ignore
34// view:
35scroll_y(
36 model.offset,
37 model.rows.len() as f32 * ROW_H,
38 panel_h,
39 lista_view,
40 Msg::ScrollBy, // Fn(f32) -> Msg, arg = delta px
41 &ScrollPalette::default(),
42)
43// update:
44Msg::ScrollBy(d) => {
45 m.offset = clamp_offset(m.offset + d, content_len, viewport_len);
46}
47```
48Para llevar una selección a la vista (teclado), ver `ensure_visible`;
49para scroll suave/inercia, ver `approach`.
50
51---
52
53Parte de **llimphi** — ver [llimphi](../../LEEME.md).
LEEME.md
llimphi-widget-scroll
Read this in English: README.md.
Área de scroll vertical reutilizable.
Hasta ahora cada app rearmaba el scroll a mano: App::on_wheel + un
offset en el Model + clip + virtualización. Este widget empaqueta
ese patrón en un solo builder, sin estado propio (el offset sigue
viviendo en el Model, fiel al bucle Elm):
- viewport clipeado de alto fijo (
viewport_len),
- contenido desplazado
-offset px (overflow recortado),
- barra de scroll arrastrable a la derecha (sólo si el contenido
excede el viewport),
- rueda autocontenida vía
View::on_scroll: girar la rueda con
el cursor sobre el área emite un Msg sin que la app rutee nada por
su on_wheel global.
El caller debe conocer el alto total del contenido (content_len)
y el alto visible (viewport_len) — igual que list/grid ya
piden la ventana visible. Para contenido de filas uniformes es
n_filas * alto_fila.
Convención del callback on_scroll
on_scroll recibe el delta en px a sumar al offset (no el offset
absoluto): tanto la rueda como el arrastre de la barra emiten deltas,
y el caller acumula + clampea en su update con clamp_offset. Es
la misma idea que el splitter (el handler de drag se reusa durante
todo el arrastre, así que un offset absoluto capturado se quedaría
viejo; el delta-por-evento siempre es correcto).
// view:
scroll_y(
model.offset,
model.rows.len() as f32 * ROW_H,
panel_h,
lista_view,
Msg::ScrollBy, // Fn(f32) -> Msg, arg = delta px
&ScrollPalette::default(),
)
// update:
Msg::ScrollBy(d) => {
m.offset = clamp_offset(m.offset + d, content_len, viewport_len);
}
Para llevar una selección a la vista (teclado), ver ensure_visible;
para scroll suave/inercia, ver approach.
Parte de llimphi — ver llimphi.