You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/uix/eidos/components/count-up/README.md

7.2 KiB

Eidos CountUp

<CountUp> es un service component — anima un número de from → to con un settle de muelle (spring) al entrar en viewport, y renderiza CADA frame a través de uix.format.numbers (locale reactivo + preferencias de separadores del runtime).

Hermano de <FormatNumber> (diseño de familia: docs/decisions/design-text-effects.md, D-T2): formatear es de FormatNumber, contar es de CountUp; ambos comparten el mismo formatter del ecosistema.

Superficie

El caso de uso real es una estadística animada de titular — un número grande que cuenta al entrar en vista, con afijos y formato:

<CountUp to={12500} suffix="+" />                             <!-- 12.500+ -->
<CountUp to={1200000} formatStyle="currency" currency="EUR" notation="compact" />  <!-- 1,2 mill € -->
<CountUp to={0.999} formatStyle="percent" maximumFractionDigits={1} />  <!-- 99,9% -->
<CountUp to={3.2} from={8} direction="down" suffix="s" maximumFractionDigits={1} />  <!-- 3,2s -->
<CountUp to={2048} formatStyle="unit" unit="byte" notation="compact" />

Renderiza data-count-up con font-variant-numeric: tabular-nums (los dígitos no bailan de ancho mientras cuenta) y, si hay prefix/suffix, cada afijo en su propio span ([data-count-up-prefix] / [data-count-up-value] / [data-count-up-suffix]) para que el consumidor pueda estilarlos.

Props clave

Prop Tipo Default Notas
to number — Valor final.
from number 0 Valor inicial.
direction 'up' | 'down' 'up' 'down' arranca en to y asienta en from.
delay number (s) 0 Espera tras entrar en viewport.
duration number (s) 2 Duración REAL del asentamiento, para cualquier magnitud (λ derivada del recorrido; A-69).
startWhen boolean true Gate adicional al viewport.
useGrouping boolean runtime Separador de millares on/off — el locale decide CUÁL.
formatStyle 'decimal' | 'currency' | 'percent' | 'unit' 'decimal' Mismo vocabulario que <FormatNumber> (mismo formatter).
currency / unit string runtime / — Para formatStyle currency / unit.
notation 'standard' | 'compact' 'standard' compact → "1,2M".
maximumFractionDigits / minimumFractionDigits number auto Precisión del display.
prefix / suffix string '' Afijos estáticos ($, +, %…) en su propio span.
locale BCP-47 runtime Override por instancia (tercer arg del runtime).
onStart / onEnd () => void — Callbacks camelCase.
as keyof HTMLElementTagNameMap 'span' Tag HTML.

Decisiones

  • Cada frame rutea por uix.format.numbers (fallback a Intl solo sin runtime) — el seed que porta (text/count) hardcodeaba Intl.NumberFormat('en-US') + un hack de replace para el separador.
  • El prop separator del seed NO se porta: los separadores son del locale/preferencias del runtime; useGrouping cubre el on/off.
  • Sí se portan prefix/suffix del seed (los afijos que lo hacen un stat, "12.500+" / "3,2s"), en spans propios con tabular-nums para que el número no salte de ancho al contar.
  • Superficie de formato completa de <FormatNumber> (formatStyle · currency · unit · notation · fracciones) — cumple la promesa D-T2 de "ambos comparten el mismo formatter": un count anima hacia una moneda, un porcentaje o un compacto, no solo un decimal pelado.
  • Decimales derivados de from/to (los que muestre el valor con más precisión), con umbral de reposo 0.5 × 10^-decimales — el muelle para en cuanto el display ya no puede cambiar.
  • Spring analítico (oscilador armónico amortiguado en forma cerrada, masa 1): el driver spring de $motion anima propiedades CSS de un elemento, no callbacks numéricos, así que no aplica aquí.
  • Ciudadanía: IO y rAF vía eidos.dom (observeIntersection / requestFrame); timers de delay/end vía eidos.timers; reduced motion vía eidos.dom.prefersReducedMotion → salta directo al valor final.
  • textContent imperativo por frame (como el seed): el update de 60fps no pasa por la reactividad de Svelte a propósito.
  • No CSS recipe: marker [data-count-up] solo para tooling.
  • No emite eventos sema.

Baseline

Port limpio del seed web/routes/demos/animations/text/count/count.svelte (colección demos/animations, intacta como referencia comparativa — D5/D7 de docs/architecture/packs.md, nota de provenance). El seed ya traía: spring DHO analítico, trigger por viewport, direction, delay/duration, startWhen, reduced-motion (salto al final). Sus déficits de ciudadanía (en-US fijo, setTimeout/IO/rAF crudos, hack de separador) son exactamente lo que este componente corrige vía runtime.

Comparativa

Capacidad Eidos countup.js react-countup number-flow
Locale reactivo desde runtime Sí No (options fijas) No Parcial (Intl estático)
Formatter compartido con el resto del sistema (uix.format) Sí No No No
Spring settle (no easing lineal) Sí easing propio easing propio Sí (transiciones)
Trigger por viewport Sí Manual/plugin Sí No (reacciona a cambios)
Reduced motion Sí No No Sí
Timers/rAF del ecosistema (cancelables, testeables) Sí No No No

Referencias externas: countup.js (https://github.com/inorganik/countUp.js) · react-countup (https://github.com/glennreyes/react-countup) · number-flow (https://number-flow.barvian.me) · Intl.NumberFormat (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat).

Gaps

  • Dígitos rodantes por columna (estilo number-flow / odometer): diferir — es otro efecto visual (máscaras por dígito), no un count; si se pide, sería componente aparte.
  • separator custom del seed: descartar — el locale del runtime es el dueño de los separadores (decisión de ciudadanía, ver Decisiones).
  • Formatos currency/unit/percent durante el count: diferir — el primer consumidor real decide si <CountUp> absorbe las options completas de <FormatNumber> o compone con él.
  • Re-count al cambiar to tras asentarse: diferir — el seed cuenta una vez por entrada en viewport; un contador "live" continuo es otro contrato.

Passive justification

Pasivo por diseño: no recibe input del usuario ni expone estados interactivos — cuenta sola al entrar en viewport y termina. Sin eventos sema (nada que percibir semánticamente: es contenido que se asienta), sin soma (no hay máquina de estados accesible), sin CSS (hereda la tipografía del contexto, como <FormatNumber>).

Referencias

  • Seed portado: web/routes/demos/animations/text/count/count.svelte (intacto como referencia comparativa, provenance en docs/architecture/packs.md).
  • Engine de números: src/arts/format/numbers/engine-numbers.ts

Audit exceptions

  • E-2.2 exception: <CountUp> is a service component — it renders locale-formatted counting text via $format, with no visual recipe of its own. No {name}.css by design.

Powered by TurnKey Linux.