Referencia de la API de Vue

Referencia completa de los componentes, los composables y las utilidades de @reelkit/vue.

Reel

Etiqueta: <Reel>

Props

ReelProps

PropTipoPor defectoDescripción
countnumberobligatorioNúmero total de slides
direction'vertical' | 'horizontal''vertical'Dirección del desplazamiento
size[number, number] | undefinedundefinedAncho y alto como [width, height]. Si se omite, el tamaño se mide con ResizeObserver
initialIndexnumber0Índice del slide inicial
loopbooleanfalseActiva el bucle infinito
transitionTransitionTransformFnslideTransitionFunción del efecto de transición. Incluidas: slideTransition, fadeTransition, flipTransition, cubeTransition, zoomTransition
transitionDurationnumber300Duración de la animación en ms
swipeDistanceFactornumber0.12Umbral del deslizamiento (0-1)
enableGesturesbooleantrueActiva la navegación arrastrando con el dedo o el ratón
enableNavKeysbooleantrueActiva la navegación con las teclas de flecha
enableWheelbooleanfalseActiva la navegación con la rueda del ratón
wheelDebounceMsnumber200Debounce de los eventos de la rueda en ms
rangeExtractor(index: number, count: number) => number[]defaultRangeExtractorFunción propia que decide qué índices se renderizan
keyExtractor(index: number, indexInRange: number) => stringindex => index.toString()Función propia de claves para renderizar los slides (útil con loop)
ariaLabelstringundefinedEtiqueta accesible de la región del carrusel
reelStyleRecord<string, string | number>undefinedEstilos en línea que se aplican al elemento contenedor raíz
reelClassstring | Array | ObjectundefinedClases CSS que se aplican al elemento contenedor raíz
onNavKeyPress(increment: -1 | 1) => voidundefinedProp de callback que sustituye la navegación por defecto con ArrowUp/ArrowDown. Si la pasas, implementas tu propia navegación (por ejemplo, llamando a reelRef.value.next()). Omítela para el comportamiento por defecto.

Eventos

EventoDatosDescripción
beforeChange(index: number, nextIndex: number, indexInRange: number)Se emite antes de que empiece la transición del slide
afterChange(index: number, indexInRange: number)Se emite al terminar la transición del slide
slideDragStart(index: number)Se emite al empezar un gesto de arrastre
slideDragEnd(index: number)Se emite al terminar un gesto de arrastre (al soltar)
slideDragCanceled(index: number)Se emite cuando se cancela un gesto de arrastre (vuelve a su sitio)
tap(event: GestureCommonEvent)Se emite con un gesto de toque simple
doubleTap(event: GestureCommonEvent)Se emite con un gesto de doble toque
longPress(event: GestureCommonEvent)Se emite al empezar una pulsación larga
longPressEnd(event: GestureEvent)Se emite al terminar una pulsación larga

Slots

vue-html
<Reel :count="items.length">
  <template #item="{ index, indexInRange, size }">
    <!-- index       : number         — absolute slide index (0 to count-1) -->
    <!-- indexInRange : number         — position in the visible window (0, 1, or 2) -->
    <!-- size         : [number,number] — [width, height] of the container -->
    <MySlide :index="index" :size="size" />
  </template>

  <!-- default slot: overlay content rendered on top of the slides -->
  <ReelIndicator />
</Reel>
SlotProps del ámbitoDescripción
#item{ index: number, indexInRange: number, size: [number, number] }Renderiza cada slide visible. Se llama para cada índice del rango virtualizado
defaultnoneContenido superpuesto que se renderiza encima de todos los slides (indicadores, controles, etc.)

ReelExpose

API imperativa expuesta a través del template ref:

vue
<script setup lang="ts">
import { ref } from 'vue';
import { Reel, type ReelExpose } from '@reelkit/vue';

const reelRef = ref<ReelExpose | null>(null);

function prev()  { reelRef.value?.prev(); }
function next()  { reelRef.value?.next(); }
function jump(i: number) { reelRef.value?.goTo(i, true); }
</script>

<template>
  <Reel ref="reelRef" :count="100">
    <template #item="{ index }">
      <div>Slide {{ index }}</div>
    </template>
  </Reel>
</template>
MétodoTipoDescripción
next()() => voidVa al slide siguiente
prev()() => voidVa al slide anterior
goTo(index, animate?)(number, boolean?) => Promise<void>Navega al índice de un slide concreto
adjust()() => voidRecalcula las posiciones de los slides (útil tras un cambio de diseño)
observe()() => voidEmpieza a escuchar los eventos de gestos, teclado y rueda
unobserve()() => voidDeja de escuchar los eventos de gestos, teclado y rueda

ReelIndicator

Etiqueta: <ReelIndicator>

Props

ReelIndicatorProps

PropTipoPor defectoDescripción
countnumber | undefinedautoNúmero total de elementos. Se conecta solo al contexto del Reel padre cuando está dentro de uno; pásalo explícitamente si lo usas por separado
activenumber | undefinedautoÍndice activo actual. Se conecta solo al contexto del Reel padre cuando está dentro de uno; pásalo explícitamente si lo usas por separado
direction'vertical' | 'horizontal''vertical'Orientación del indicador
radiusnumber3Radio del punto en píxeles
visiblenumber5Máximo de puntos visibles a la vez a tamaño normal
gapnumber4Espacio entre puntos en píxeles
activeColorstring'#fff'Color del punto activo
inactiveColorstring'rgba(255, 255, 255, 0.5)'Color de los puntos inactivos
edgeScalenumber0.5Factor de escala de los puntos de los bordes que desbordan
onDotClick(index: number) => voidundefinedManejador de clic propio. Si se omite dentro de un Reel, por defecto navega al índice del punto pulsado
indicatorClassstring | Array | ObjectundefinedClases CSS que se aplican al elemento raíz del tablist
indicatorStyleCSSPropertiesundefinedEstilos en línea que se combinan con los del elemento raíz del tablist

Eventos

EventoDatosDescripción
dotClick(index: number)Se emite al hacer clic en un punto; incluye el índice del punto

SwipeToClose

Etiqueta: <SwipeToClose>. Envuelve su slot por defecto en un contenedor que responde al tacto y que se puede deslizar para cerrar.

Props

SwipeToCloseProps

PropTipoPor defectoDescripción
direction'up' | 'down'obligatorioDirección del deslizamiento que cierra. Usa "up" para cerrar un lightbox y "down" para cerrar stories
enabledbooleantrueIndica si el gesto de deslizar para cerrar está activo
thresholdnumber0.2Fracción de la altura del viewport necesaria para cerrar (0-1)

Eventos

EventoDatosDescripción
close()Se emite cuando el gesto supera el umbral y termina la animación de cierre

Slots

SlotDescripción
defaultContenido que se envuelve con la gestión del gesto de deslizar para cerrar

RK_REEL_KEY y useReelContext

Una InjectionKey<ReelContextValue> que <Reel> proporciona a sus descendientes. <ReelIndicator> la usa internamente para conectarse solo. Usa useReelContext() en componentes propios que necesiten el contexto del slider.

vue
<script setup lang="ts">
import { useReelContext } from '@reelkit/vue';

const ctx = useReelContext();

function jump(index: number) {
  ctx?.goTo(index, true);
}
</script>
PropiedadTipoDescripción
indexSignal<number>Índice reactivo del slide actual
countSignal<number>Recuento reactivo del total de elementos
goTo(index: number, animate?: boolean) => Promise<void>Navega a un slide por código

Composables

useBodyLock

Bloquea el scroll del body del documento cuando el valor pasado es true. Usa recuento de referencias, así que varios llamadores a la vez pueden bloquear y desbloquear cada uno por su cuenta. Se desbloquea solo al desmontar.

typescript
import { ref } from 'vue';
import { useBodyLock } from '@reelkit/vue';

const isOpen = ref(false);
useBodyLock(isOpen);

// Also accepts a static boolean
useBodyLock(true);
ParámetroTipoDescripción
lockedRef<boolean> | booleanIndica si el scroll del body debe bloquearse. Acepta un ref reactivo o un booleano estático

useFullscreen

UseFullscreenOptionsUseFullscreenReturn

Composable para gestionar la Fullscreen API, compatible con todos los navegadores. Sale de la pantalla completa automáticamente al desmontar.

typescript
import { ref } from 'vue';
import { useFullscreen } from '@reelkit/vue';

const containerRef = ref<HTMLElement | null>(null);
const { isFullscreen, request, exit, toggle } = useFullscreen({
  elementRef: containerRef,
});
DevuelveTipoDescripción
isFullscreenSignal<boolean>Señal del core con el estado actual de pantalla completa (lee .value)
request() => Promise<void>Pone en pantalla completa el elemento referenciado. Si ya hay otro elemento en pantalla completa, primero sale de ella (y lo espera).
exit() => Promise<void>Sale de la pantalla completa
toggle() => Promise<void>Alterna el estado de pantalla completa

useSoundState

Accede al SoundController actual desde el contexto. Debe llamarse dentro de un <SoundProvider>; fuera de él lanza un error.

typescript
import { useSoundState } from '@reelkit/vue';

// Inside a SoundProvider descendant
const sound = useSoundState();

sound.muted;    // Signal<boolean>
sound.toggle(); // Toggle muted state

useOverlayUrlState

OverlayUrlStateOptions

Crea un controlador de estado en la URL para un overlay, que después pasas a un <LightboxUrlOverlay> en su prop :controller.

Consulta el estado en la URL en la guía de Vue para ver la explicación paso a paso y los ejemplos.

OpciónTipoPor defectoDescripción
paramstringobligatorioParámetro de la query que lleva el slide activo, por ejemplo "photo".
adapterUrlAdapterHistory APISistema de navegación con el que leer y escribir. En una aplicación con router, pasa un adaptador basado en el router para que su propia ubicación no quede desfasada.
codec{ decode(raw) => Id | null; encode(id) => string }obligatorioFormato: texto del parámetro ↔ una identidad estable, sin conocer la colección. Va con locator como un par a juego que comparte el mismo Id: usa ...urlIndexKey(() => props.images.length) para la galería por índice ?photo=3 por defecto, o aporta uno propio (base64, slug) para que un marcador sobreviva a que la galería se reordene.
locator{ locate(id) => number | null; locateAsync?(id) => Promise<number | null>; identify(index) => id }obligatorioConvierte la identidad en una posición y decide su propia validez: locate (síncrono), locateAsync (alternativa asíncrona para una galería paginada), identify (escrituras). Para una galería por índice simple usa ...urlIndexKey(() => props.images.length): aporta este locator más el codec a juego y limita ?photo=3 con el recuento actual, así que un ?photo=99 desfasado se limpia de la URL en lugar de abrir un slide que nunca se nombró. Pasa un getter y no un número, porque el setup de Vue se ejecuta una sola vez y una longitud capturada quedaría desfasada mientras crece un feed paginado. Un feed paginado o una galería por identidad aporta su propio par de codec + locator.

useVueRouterUrlAdapter

Un UrlAdapter basado en Vue Router. Pásalo como opción adapter de useOverlayUrlState en una aplicación con router para que el router siga siendo la única fuente de verdad de la navegación: escribir con history.pushState a sus espaldas deja su ubicación desfasada y su siguiente navegación pierde el parámetro. Las escrituras solo tocan la query, así que la ruta, el hash y las claves repetidas como ?tag=a&tag=b se mantienen intactos. Cada cambio indica si el router hizo push en la misma página, sustituyó la entrada o se movió por el historial, así que una galería abierta desde un <router-link> se cierra volviendo atrás una vez.

Se publica en su propia subruta, así que una aplicación sin router nunca mete vue-router en su bundle. vue-router es una peer dependency opcional, de la versión 4.1 o posterior: el adaptador guarda su marca de propiedad en la opción de navegación state del router, que las versiones anteriores ignoran. Con un router más antiguo no se rompe nada; simplemente, al cerrar se limpia el parámetro en el sitio en lugar de volver atrás.

typescript
import { useVueRouterUrlAdapter } from '@reelkit/vue/vue-router-url-adapter';

const adapter = useVueRouterUrlAdapter();
const photo = useOverlayUrlState({
  param: 'photo',
  adapter,
  ...urlIndexKey(() => props.images.length),
});

toVueRef

Convierte un Subscribable del core (cualquier Signal de @reelkit/core) en un Ref de Vue de solo lectura. Úsalo siempre que el valor de una señal del core deba provocar un re-renderizado en Vue: leer signal.value directamente en funciones de renderizado o plantillas no es reactivo por sí solo.

La suscripción se libera sola con onScopeDispose, así que hay que llamarlo dentro del setup() de Vue o de otro contexto con ámbito de efectos.

typescript
import { defineComponent, h } from 'vue';
import { toVueRef, useSoundState } from '@reelkit/vue';

export const MuteIcon = defineComponent({
  setup() {
    const sound = useSoundState();
    const muted = toVueRef(sound.muted); // Readonly<Ref<boolean>>

    return () => h('span', muted.value ? '🔇' : '🔊');
  },
});

SoundProvider

Etiqueta: <SoundProvider>. Proveedor de contexto que crea una instancia de SoundController y la pone a disposición de sus descendientes a través de RK_SOUND_KEY. Renderiza su slot por defecto de forma transparente.

vue
<template>
  <SoundProvider>
    <Reel :count="items.length">
      <template #item="{ index }">
        <VideoSlide :index="index" />
      </template>
      <MuteButton />
    </Reel>
  </SoundProvider>
</template>

Accesibilidad

<Reel> se renderiza como role="region" con aria-roledescription="carousel". Pasa aria-label (en TS la prop es ariaLabel) para darle a la región un nombre para los lectores de pantalla. Una región en vivo educada anuncia "Slide N of M" en cada cambio de slide. Los slides inactivos reciben el atributo inert, así que el foco y la navegación con tecnologías de apoyo se los saltan.

<ReelIndicator> se renderiza como role="tablist" con tabindex itinerante en los puntos; las flechas mueven el foco y Intro o Espacio activan el slide.

¿Vas a crear un modal propio alrededor de <Reel>? captureFocusForReturn, createFocusTrap y getFocusableElements se reexportan desde @reelkit/vue para devolver y atrapar el foco.

Exports del paquete

Todos los exports públicos de @reelkit/vue:

typescript
// Components
import {
  Reel,
  ReelIndicator,
  SwipeToClose,
  SoundProvider,
} from '@reelkit/vue';

// Types
import type {
  ReelExpose,
  ReelContextValue,
  SwipeToCloseDirection,
  SwipeToCloseProps,
  UseFullscreenOptions,
  UseFullscreenReturn,
} from '@reelkit/vue';

// Context & composables
import {
  RK_REEL_KEY,
  useReelContext,
  RK_SOUND_KEY,
  useBodyLock,
  useFullscreen,
  useSoundState,
  toVueRef,
} from '@reelkit/vue';

// Utilities (re-exported from @reelkit/core)
import {
  createDefaultKeyExtractorForLoop,
  defaultRangeExtractor,
} from '@reelkit/vue';

// Core re-exports
import {
  // Signals & reactivity
  createSignal, createComputed, reaction, batch, createDeferred,

  // Transitions
  slideTransition, fadeTransition, flipTransition,
  cubeTransition, zoomTransition, getSlideProgress,

  // Content loading & preloading
  createContentLoadingController, createContentPreloader,
  observeMediaLoading,

  // Sound
  createSoundController, syncMutedToVideo,

  // Fullscreen
  fullscreenSignal, requestFullscreen, exitFullscreen,

  // DOM & cleanup
  observeDomEvent, createDisposableList, createBodyLock, sharedBodyLock,

  // Focus management
  captureFocusForReturn, createFocusTrap, getFocusableElements,

  // Gestures
  createGestureController,

  // Video
  captureFrame, createSharedVideo,

  // Animation
  animate,

  // Utilities
  noop, clamp, abs, first, last, extractRange,
  lerp, isNegative, generate,
} from '@reelkit/vue';