Core-API-Referenz

Vollständige Referenz für Konfiguration, Callbacks, Methoden und Zustand von @reelkit/core.

SliderController-API

Der Core, unabhängig vom Framework. Eine Factory baut einen Controller aus einer Konfiguration und optionalen Events: Die Konfigurationsoptionen sind die Konfiguration, die Callbacks die Events, und die Methoden sind das, was der zurückgegebene Controller bereitstellt.

Factory-Funktion

ExportTypBeschreibung
createSliderController(config: SliderConfig, events?: SliderEvents) => SliderControllerBaut einen Slider-Controller. config ist erforderlich (Optionen unten); events ist optional (Callbacks unten). Gibt den Controller zurück, dessen Methoden ihn steuern.

Konfigurationsoptionen

EigenschaftTypStandardBeschreibung
countnumberPflichtGesamtzahl der Elemente
initialIndexnumber0Startindex
directionSliderDirection'vertical'Scrollrichtung, 'vertical' | 'horizontal'
enableGesturesbooleantrueAktiviert die Navigation durch Ziehen mit Finger oder Maus. Bei false wird der Gesture-Controller nicht angehängt.
enableNavKeysbooleantrueAktiviert die Navigation mit den Pfeiltasten
enableWheelbooleanfalseAktiviert das Mausrad
wheelDebounceMsnumber200Debounce-Zeit des Mausrads
loopbooleanfalseNavigation in Schleife
transitionDurationnumber300Dauer der Animation in ms
swipeDistanceFactornumber0.12Schwelle für das Wischen (0-1)
rangeExtractorRangeExtractordefaultRangeExtractorEigene Funktion, die bestimmt, welche Indizes gerendert werden

Callbacks

CallbackTypBeschreibung
onBeforeChange(index, nextIndex, rangeIndex) => voidVor dem Slidewechsel
onAfterChange(index, rangeIndex) => voidNach dem Slidewechsel
onDragStart(index) => voidZiehen hat begonnen
onDragEnd(index) => voidZiehen ist beendet
onDragCanceled(index) => voidZiehen wurde abgebrochen
onTap(event: GestureCommonEvent) => voidEinfaches Tippen (verzögert um das Fenster für Doppeltippen)
onDoubleTap(event: GestureCommonEvent) => voidDoppeltippen erkannt
onLongPress(event: GestureCommonEvent) => voidLanges Drücken erkannt
onLongPressEnd(event: GestureEvent) => voidZeiger nach langem Drücken losgelassen
onNavKeyPress(increment: -1 | 1) => voidEigener Handler für die Navigation mit Pfeiltasten. Ersetzt das Standardverhalten für vorherigen und nächsten Slide.

Methoden

MethodeTypBeschreibung
attach(element)(HTMLElement) => voidVerbindet den Controller für die Gestenerkennung mit einem DOM-Element
detach()() => voidEntfernt die DOM-Listener (Gesten, Tastatur, Mausrad). Sicher für ein erneutes Anhängen über observe(). Für das Aufräumen von React-Effects.
dispose()() => voidEndgültiger Abbau: hängt alle Controller ab und räumt die Signal-Observer auf. Für onDestroy in Angular.
observe()() => voidStartet die Beobachtung von Gesten, Tastatur und Mausrad. Beachtet die Konfigurationsflags enableGestures, enableNavKeys und enableWheel.
unobserve()() => voidBeendet die Beobachtung von Gesten, Tastatur und Mausrad
next()() => Promise<void>Geht zum nächsten Slide
prev()() => Promise<void>Geht zum vorherigen Slide
goTo(index, animate?)(number, boolean?) => Promise<void>Geht zu einem bestimmten Slide
adjust(duration?)(number?) => voidBerechnet die Positionen der Slides neu
setPrimarySize(size)(number) => voidAktualisiert die Größe des Containers
updateConfig(config)(Partial<SliderConfig>) => voidAktualisiert Konfigurationsoptionen
updateEvents(events)(Partial<SliderEvents>) => voidErsetzt Event-Handler (nicht übergebene Handler bleiben erhalten)
getRangeIndex()() => numberGibt die Position des aktiven Index im Array des sichtbaren Bereichs zurück

Zustandseigenschaften

Das Feld state des Controllers ist ein SliderState, also die drei Signals unten. Typisiere damit einen Wert, der es entgegennimmt.

EigenschaftTypBeschreibung
indexSignal<number>Index des aktuellen Slides
axisValueSignal<AnimatedValue>Aktuelle Position auf der Achse (animiert)
indexesComputedSignal<number[]>Sichtbare Indizes für die Virtualisierung

Range-Extractor

ExportTypBeschreibung
defaultRangeExtractorRangeExtractorStandard-Extractor, der 3 Elemente um den aktuellen Index rendert
RangeExtractor(current: number, count: number, loop: boolean) => number[]Signatur eines Range-Extractors. Typisiere damit deinen eigenen rangeExtractor.

Signal-API

Schlanke reaktive Grundbausteine, die im ganzen Core verwendet werden.

Signal-Interface

MemberTypBeschreibung
valueTLiest oder setzt den aktuellen Wert. Das Setzen benachrichtigt die Observer, wenn sich der Wert geändert hat.
observe(callback)(callback: () => void) => () => voidRegistriert einen Listener, der bei jeder Wertänderung aufgerufen wird. Gibt eine Dispose-Funktion zurück, die den Listener entfernt.

Factory-Funktionen

ExportTypBeschreibung
createSignal<T>(initial: T) => Signal<T>Erstellt ein veränderbares reaktives Signal
createComputed<T>(fn: () => T, deps: () => Subscribable[]) => ComputedSignal<T>Erstellt ein abgeleitetes Computed-Signal. Das zweite Argument ist eine Factory für die Abhängigkeiten, die die zu verfolgenden Signals zurückgibt.
reaction(deps: () => Subscribable[], effect: () => void) => () => voidFührt einen Seiteneffekt aus, wenn sich ein abhängiges Signal ändert; gibt eine Dispose-Funktion zurück. Lies die Werte der Signals im Effect-Callback.
batch(fn: () => void) => voidFasst mehrere Signal-Updates zu einer einzigen Benachrichtigung zusammen; lässt sich verschachteln
Listener() => voidDer Callback, den observe entgegennimmt. Typisiere damit einen Observer, den du separat deklarierst.
Dispose() => voidWas observe und reaction zurückgeben: Rufe es auf, um das Zuhören zu beenden. Typisiere damit ein gespeichertes Abonnement.

Übergänge

Eingebaute Übergangsfunktionen, die während der animierten Navigation CSS-Transforms pro Slide berechnen. Übergib eine davon als Prop transitionTransformFn an die Komponente des Frameworks.

ExportTypBeschreibung
TransitionTransformFntypeSignatur für eigene Übergangsfunktionen
getSlideProgress(axisValue: number, slideIndex: number, primarySize: number) => numberGibt einen normierten Versatz (-1 bis 1) eines Slides relativ zum Viewport zurück. Für eigene Übergangsfunktionen.
slideTransitionTransitionTransformFnStandardübergang als Verschiebung (translateX/Y)
fadeTransitionTransitionTransformFnÜberblendung über die Deckkraft
flipTransitionTransitionTransformFn3D-Übergang, bei dem die Karte umgedreht wird
cubeTransitionTransitionTransformFn3D-Übergang als rotierender Würfel
zoomTransitionTransitionTransformFnÜbergang durch Skalieren und Zoomen
SlideTransformStyle{ transform?; transformOrigin?; opacity?; zIndex? }Was eine TransitionTransformFn für einen Slide zurückgibt. Gib es aus einem eigenen Übergang zurück.

Eingabe-Controller

Der Slider-Controller baut diese drei selbst aus seinen Optionen enableGestures, enableNavKeys und enableWheel. Erstelle einen direkt, wenn du eine eigene Integration schreibst oder Gesten, Pfeiltasten oder das Mausrad auf einem Element brauchst, das kein Slider ist.

Gesture-Controller

ExportTypBeschreibung
createGestureController(config?: GestureControllerConfig, events?: GestureControllerEvents) => GestureControllerErkennt Tippen, Doppeltippen, langes Drücken und Ziehen auf einem Element und legt jedes Ziehen auf seine vorherrschende Achse fest.
GestureController{ attach; detach; observe; unobserve; updateEvents }Objekt, das createGestureController zurückgibt. attach(element) bindet das Element, observe() fügt die Listener hinzu, unobserve() entfernt sie und behält das Element, detach() entfernt alles; updateEvents(events) mischt neue Handler hinzu.
GestureControllerConfig{ useTouchEventsOnly?; longPressDurationMs?; doubleTapWindowMs? }Optionen von createGestureController: die Maus ignorieren (Standard false), Dauer für langes Drücken (Standard 800 ms), Fenster für Doppeltippen (Standard 200 ms).
GestureControllerEvents{ onTap?; onDoubleTap?; onTapDown?; onTapUp?; onLongPress?; onLongPressEnd?; onHorizontalDragStart?; onHorizontalDragUpdate?; onHorizontalDragEnd?; onVerticalDragStart?; onVerticalDragUpdate?; onVerticalDragEnd?; onDragEnd? }Callbacks, die createGestureController aufruft. Ein Ziehen geht je nach vorherrschender Achse an die horizontalen oder vertikalen Handler; onDragEnd feuert für beide.
GestureAxisDragUpdateEventGestureEvent & { delta; distance; primaryDelta; primaryDistance; cancel }Payload von onHorizontalDragUpdate und onVerticalDragUpdate: Bewegung seit dem letzten Update, Gesamtstrecke, beides entlang der vorherrschenden Achse und cancel(), um das Ziehen zurückschnappen zu lassen.
GestureAxisDragEndEventGestureAxisDragUpdateEvent ohne cancel, dazu { velocity; primaryVelocity }Payload von onHorizontalDragEnd und onVerticalDragEnd, mit der Geschwindigkeit beim Loslassen in Pixeln pro Sekunde.
GestureDragEndEventGestureAxisDragEndEvent ohne die Felder primaryPayload von onDragEnd, für einen Handler, dem die Achse des Ziehens egal ist.
Offset[x: number, y: number]Ein Paar aus Pixelwerten, genutzt für jede Position, jedes Delta, jede Strecke und jede Geschwindigkeit in einem Gesten-Event.
EventKind'touch' | 'mouse'Die Eingabe, von der eine Geste kam, im Feld kind von GestureCommonEvent.
DragAxis'horizontal' | 'vertical' | nullDie vorherrschende Achse eines Ziehens, null, bis die erste Bewegung sie festlegt.

Tastatur-Controller

ExportTypBeschreibung
createKeyboardController(config: KeyboardControllerConfig, events: KeyboardControllerEvents) => KeyboardControllerMacht aus Druck auf die Pfeiltasten Callbacks mit NavKey.
KeyboardController{ attach; detach }Objekt, das createKeyboardController zurückgibt. attach(target?) hört auf keydown am Ziel (Standard window), detach() hört damit auf.
KeyboardControllerConfig{ filter?; throttleMs? }Optionen von createKeyboardController: die Tasten, auf die er reagiert (Standard: alle vier), und die kürzeste Zeit zwischen zwei Tastendrücken (Standard 0, ohne Drosselung).
KeyboardControllerEvents{ onKeyPress: (key: NavKey, event: KeyboardEvent) => void }Callback, den createKeyboardController für jeden angenommenen Tastendruck aufruft.
NavKey'up' | 'right' | 'down' | 'left'Die gedrückte Pfeiltaste, so wie der Tastatur-Controller sie meldet und filtert.

Mausrad-Controller

ExportTypBeschreibung
createWheelController(config: WheelControllerConfig, events: WheelControllerEvents) => WheelControllerMacht aus Scrollen mit dem Mausrad einen Callback mit Richtung pro Geste und fasst die Flut von Events zusammen, die ein einzelnes Scrollen auslöst.
WheelController{ attach; detach }Objekt, das createWheelController zurückgibt. attach(target?) hört auf wheel am Ziel (Standard window), detach() hört damit auf und verwirft einen ausstehenden Callback.
WheelControllerConfig{ debounceMs?; deltaThreshold? }Optionen von createWheelController: die Ruhezeit, die eine Geste beendet (Standard 200 ms), und das kleinste Delta, das zählt (Standard 10 px).
WheelControllerEvents{ onWheel: (direction: WheelDirection, event: WheelEvent) => void }Callback, den createWheelController einmal pro Scrollgeste aufruft.
WheelDirection'up' | 'down' | 'left' | 'right'Die Richtung einer Mausradgeste.

Laden von Inhalten

Hilfsfunktionen, die Lade- und Fehlerzustände pro Slide verfolgen und Medien vorladen. Der Loading-Controller nutzt eine Prüfung des Index, um veraltete Callbacks von zuvor aktiven Slides abzuweisen. Der Preloader nutzt einen LRU-Cache (standardmäßig 200 geladene, 100 fehlerhafte), sodass ein erneuter Besuch einer kaputten URL den Fehler sofort und ohne neuen Versuch zeigt.

ExportTypBeschreibung
createContentLoadingController() => ContentLoadingControllerVerfolgt Lade- und Fehlerzustände pro Slide
createContentPreloader(config: ContentPreloaderConfig) => ContentPreloaderPreloader für Medien mit LRU-Cache, der auch Fehler zwischenspeichert
observeMediaLoading(video: HTMLVideoElement, callbacks: MediaLoadingCallbacks) => () => voidBeobachtet den Ladezustand eines Videos (playing, canplaythrough, waiting). Gibt einen Disposer zurück.

ContentLoadingController

ExportTypBeschreibung
isLoadingSignal<boolean>Ob der aktive Slide gerade lädt
isErrorSignal<boolean>Ob beim aktiven Slide ein Fehler aufgetreten ist
setActiveIndex(index: number) => voidAktualisiert den aktiven Index und setzt den Lade- und Fehlerzustand zurück
onReady(index: number) => voidMarkiert einen Slide als bereit (ignoriert, wenn der Index nicht der aktive ist)
onWaiting(index: number) => voidMarkiert einen Slide als ladend (ignoriert, wenn der Index nicht der aktive ist)
onError(index: number) => voidMarkiert einen Slide als fehlerhaft (ignoriert, wenn der Index nicht der aktive ist)

ContentPreloader

ExportTypBeschreibung
preload(src: string, type?: "image" | "video") => voidBeginnt, eine Medien-URL vorzuladen
isLoaded(src: string) => booleanPrüft, ob die URL im LRU-Cache der geladenen Medien liegt (höchstens 200)
isErrored(src: string) => booleanPrüft, ob die URL im LRU-Cache der Fehler liegt (höchstens 100)
markLoaded(src: string) => voidMarkiert eine URL von Hand als geladen
markErrored(src: string) => voidMarkiert eine URL von Hand als fehlerhaft
onLoaded(src: string, cb: () => void) => () => voidAbonniert das Ende des Ladens; gibt einen Disposer zurück

Ton

Gemeinsamer Zustand für Stumm und Laut bei der Medienwiedergabe. Der Sound-Controller stellt ein reaktives Signal für die Stummschaltung bereit, das sich mit Videoelementen synchronisieren und über eigene Bedienelemente umschalten lässt.

ExportTypBeschreibung
createSoundController() => SoundControllerController für den gemeinsamen Zustand der Stummschaltung
syncMutedToVideo(video: HTMLVideoElement, sound: SoundController) => () => voidSynchronisiert das Signal der Stummschaltung mit einem Videoelement. Gibt einen Disposer zurück.

Zeitleiste

Controller für die Zeitleiste der Wiedergabe zum Spulen in Videos. Verfolgt Dauer, aktuelle Zeit, gepufferte Bereiche und den Spulzustand des Nutzers als reaktive Signals. Ein einziger Aufruf verbindet Pointer- und Tastatur-Interaktionen mit einem beliebigen DOM-Element, sodass es sich wie eine native Zeitleiste verhält, mit Pointer-Capture, Live-Spulen und voller Tastaturunterstützung (Pfeiltasten, Pos1/Ende, Bild auf/Bild ab).

ExportTypBeschreibung
createTimelineController(config?: TimelineControllerConfig) => TimelineControllerFactory für einen Controller mit den Signals duration, currentTime, progress, bufferedRanges und isScrubbing sowie den Methoden attach, detach, bindInteractions und seek.
TimelineControllerConfiginterfacekeyboardStepSeconds (Standard 5), keyboardPageFraction (Standard 0.1) und die Callbacks onSeek, onScrubStart, onScrubEnd.
BufferedRange{ start: number; end: number }Ein einzelner zusammenhängender gepufferter Bereich als Anteile von 0 bis 1 der Gesamtdauer. Sortiert und ohne Überlappung ausgegeben.

Vollbild

Hilfsfunktionen für das Vollbild über Browser hinweg, mit Absicherung der Präfixe für Safari. Das Signal für das Vollbild ist ein lazy erzeugtes Singleton, das den Vollbildzustand reaktiv verfolgt.

ExportTypBeschreibung
fullscreenSignalSignal<boolean>Reaktives Signal, das verfolgt, ob das Dokument im Vollbildmodus ist
requestFullscreen(element: HTMLElement) => Promise<void>Schaltet das übergebene Element in den Vollbildmodus
exitFullscreen() => Promise<void>Beendet den Vollbildmodus

DOM- und Aufräum-Hilfsfunktionen

Einfache Helfer für die Verwaltung von DOM-Events und ein deterministisches Aufräumen. Intern von allen Controllern genutzt und für eigene Integrationen verfügbar.

ExportTypBeschreibung
observeDomEvent(target, event, handler, options?) => () => voidFügt einen DOM-Event-Listener hinzu und gibt einen Disposer zurück, der ihn entfernt
createDisposableList() => DisposableListZusammensetzbare Liste zum Sammeln von Disposer-Funktionen. Rufe dispose() auf, um alle auf einmal auszuführen.
createBodyLock() => BodyLockScroll-Sperre für den Body mit Referenzzählung. Mehrere Nutzer können gleichzeitig sperren; das Scrollen kehrt zurück, wenn alle entsperrt haben.
sharedBodyLockBodyLockSingleton-Instanz auf Modulebene. Nutze sie, wenn mehrere Komponenten deiner App einen einzigen Referenzzähler teilen sollen, damit verschachtelte Modals und Overlays richtig ineinandergreifen. Die Bindings der Frameworks (@reelkit/react, @reelkit/vue, @reelkit/angular) nutzen sie intern.

Hilfsfunktionen

Kleine Helfer, aus denen die Controller gebaut sind. Die Bindings der Frameworks exportieren sie weiter, sodass ein eigener Slide, ein eigener Übergang oder eine eigene Integration dieselben nutzen kann.

ExportTypBeschreibung
first<T>(arr: readonly T[]) => TErstes Element eines Arrays, etwa das x eines Offset oder die Breite einer Größe.
last<T>(arr: readonly T[]) => TLetztes Element eines Arrays, etwa das y eines Offset oder die Höhe einer Größe.
generate<G>(count: number, generator: (i: number) => G) => G[]Baut ein Array aus count Elementen anhand ihres Index, zum Beispiel generate(10, (i) => i) für Demodaten.
abs(value: number) => numberAbsolutwert.
isNegative(value: number) => booleanOb eine Zahl kleiner als null ist, etwa um ein Ziehen nach hinten von einem nach vorn zu unterscheiden.
clamp(value: number, min: number, max: number) => numberHält eine Zahl zwischen min und max, beide eingeschlossen.
lerp(t: number, a: number, b: number) => numberLineare Interpolation: a bei t = 0, b bei t = 1. Nutze sie in einem eigenen Übergang, um den Fortschritt eines Slides auf einen Wert abzubilden.
extractRange(count, start, end?, overscan?, loop?) => number[]Indizes von start bis end (Standard start) plus overscan auf jeder Seite (Standard 1), an den Enden umgebrochen, wenn loop true ist. Baue damit einen eigenen RangeExtractor.
noop() => voidEine Funktion, die nichts tut, für einen Standard-Callback.
createDeferred<T = void>() => Deferred<T>Ein Promise zusammen mit dem resolve, das es erfüllt, um eine Callback-API mit await zu verbinden.
Deferred{ promise: Promise<T>; resolve: (value?: T) => void }Objekt, das createDeferred zurückgibt.
createLruCache<V>(maxSize: number, onEvict?: (value: V, key: string) => void) => LruCache<V>Eine Map, die die maxSize zuletzt gesetzten Einträge behält und darüber hinaus die ältesten verwirft. onEvict läuft für jeden verworfenen Eintrag, zum Aufräumen wie mit URL.revokeObjectURL.
LruCacheMap<string, V>Objekt, das createLruCache zurückgibt. Es ist eine echte Map; nur set verhält sich anders.
animate(options: AnimationOptions) => () => voidAnimiert eine Zahl von from nach to mit einer Ease-in-out-Kurve und ruft onUpdate in jedem Frame auf. Gibt eine Funktion zurück, die die Animation abbricht.
AnimationOptions{ from; to; duration; onUpdate; onComplete? }Optionen von animate: Start- und Endwert, Dauer in Millisekunden, der Callback pro Frame und ein optionaler Callback am Ende.

Größenerkennung

Wie jedes Binding und jedes Overlay seinen Container und das Fenster misst. Reel nutzt observeElementSize, wenn kein size übergeben wird; der Reel Player, die Lightbox und der Stories Player richten ihre Größe nach dem Fenster. Sicher für SSR: Ohne Fenster oder ResizeObserver geben die Getter [0, 0] oder false zurück, und die Observer geben einen Disposer zurück, der nichts tut.

ExportTypBeschreibung
observeElementSize(element: Element, callback: (size: [number, number]) => void) => DisposerMeldet die Padding-Box des Elements (clientWidth × clientHeight), wann immer sie sich ändert. Überspringt eine Größe mit einer Seite von null (versteckt oder noch nicht gelayoutet) und eine Größe, die der zuletzt gemeldeten gleicht.
getViewportSize() => [number, number]Die Größe des Fensters als [innerWidth, innerHeight].
observeViewportSize(callback: (size: [number, number]) => void) => DisposerRuft bei jedem resize-Event mit der Fenstergröße zurück, auch bei einem, das die Größe nicht ändert (die Geräteemulation kann zu einem Touch-Gerät mit denselben Maßen wechseln). Vergleiche die Größen selbst, wenn nur eine Änderung zählt.
isMobileWidth(viewportWidth: number) => booleanOb ein so breites Fenster das Smartphone-Layout bekommt: 768px und schmaler. Jedes Overlay und sein Stylesheet wechseln bei dieser Breite.
fitAspectRatio(viewport: [number, number], aspectRatio?: number) => [number, number]Größe des Overlays für ein Fenster. Bei Smartphone-Breite ist es das ganze Fenster; sonst die volle Fensterhöhe im Seitenverhältnis aspectRatio, auf die Fensterbreite verschmälert, wenn es sonst nicht passt. Ein fehlendes, negatives, unendliches oder auf null gesetztes Verhältnis fällt auf 9/16 zurück.
isTouchDevice() => booleanOb das Gerät Touch-Eingaben annimmt (ontouchstart oder maxTouchPoints). Eine Prüfung der Fähigkeit, nicht der Bildschirmgröße: Ein Laptop mit Touchscreen zählt, ein schmales Desktop-Fenster nicht.

Autoplay

Timer für alles, was von selbst weitergeht. Wie sie sich verhalten und wie du sie verbindest, steht im Autoplay-Guide.

ExportTypBeschreibung
createTimerController(config: TimerControllerConfig) => TimerControllerZählt eine Dauer von 0 bis 1 und ruft zurück, wenn sie vorbei ist. Treibt jede Story in den Stories Playern an.
createSlideshowController(config: SlideshowControllerConfig) => SlideshowControllerDie Zustandsmaschine hinter einer Galerie, die von selbst weitergeht. Treibt autoAdvance der Lightbox an.

createTimerController

TimerControllerConfigTypBeschreibung
durationnumberStandarddauer in Millisekunden, genutzt, wenn start() keine bekommt
onComplete() => voidWird aufgerufen, wenn der Fortschritt 1 erreicht
TimerControllerTypBeschreibung
progressSignal<number>Fortschritt von 0 bis 1; treibt eine Fortschrittsleiste an
isRunningSignal<boolean>Ob der Timer zählt
start(duration?)(number?) => voidBeginnt neu bei 0, optional mit einer anderen Dauer für diesen Lauf
pause()() => voidHält beim aktuellen Fortschritt an
resume()() => voidMacht beim angehaltenen Fortschritt weiter
reset()() => voidZurück auf 0, angehalten
dispose()() => voidBricht den ausstehenden Frame ab

createSlideshowController

SlideshowControllerConfigTypBeschreibung
intervalnumberWie lange ein Bild bleibt, in Millisekunden, gezählt ab dem Laden
onAdvance() => voidDer aktive Slide ist fertig. Gehe zum nächsten Slide oder rufe beim letzten pause() auf
SlideshowControllerTypBeschreibung
isPlayingSignal<boolean>Ob die Diashow eingeschaltet ist. Anhaltegründe ändern das nicht
progressSignal<number>Wie weit das Intervall des aktiven Bilds gelaufen ist, von 0 bis 1
play() / pause() / toggle()() => voidSchaltet sie ein oder aus; der aktive Slide behält seinen Fortschritt
setInterval(ms)(number) => voidÄndert das Intervall ab dem nächsten Bild
setSlide(kind)(SlideshowSlideKind) => voidEin neuer Slide ist aktiv: Der Fortschritt beginnt neu und wartet auf ready() oder ended(). SlideshowSlideKind ist 'image' | 'video'
ready()() => voidDas aktive Bild ist geladen oder konnte nicht laden; sein Intervall beginnt
ended()() => voidDas aktive Video ist zu Ende; geht jetzt weiter oder sobald nichts mehr anhält
hold(reason) / release(reason)(string) => voidHält die Uhr aus einem Grund wie 'hover' oder 'drag' an. Gründe stapeln sich
dispose()() => voidHält die Uhr und den Listener für die Sichtbarkeit an

Download

Eine Datei von einer URL speichern, auch von einem anderen Origin. Der Fallback, den es nimmt, steht im Download-Guide.

ExportTypBeschreibung
downloadFile(url: string, filename?: string) => Promise<void>Speichert eine Datei unter filename, standardmäßig unter dem letzten Segment des Pfads der URL. Holt die Datei und speichert den Blob, weil das Attribut download bei einem Link auf einen anderen Origin ignoriert wird. Schlägt der Abruf fehl oder antwortet der Server mit einem Fehler (üblicherweise ein fremder Server ohne CORS-Header), öffnet sich stattdessen die URL in einem neuen Tab. Lehnt nie ab; tut nichts ohne ein Fenster.

Fokusverwaltung

Bausteine für die Barrierefreiheit von Dialogen, unabhängig vom Framework. Die Overlay-Pakete nutzen sie, um den Fokus beim Schließen an den Auslöser zurückzugeben und Tab / Umschalt+Tab im Overlay zu halten, solange es offen ist. Sicher für SSR: Jeder Helfer gibt außerhalb des Browsers einen Disposer zurück, der nichts tut.

ExportTypBeschreibung
captureFocusForReturn() => DisposerMerkt sich das aktuell fokussierte Element und gibt einen Disposer zurück, der es wieder fokussiert. Nach bestem Bemühen: Der Disposer tut nichts, wenn das gemerkte Element inzwischen aus dem DOM entfernt wurde.
createFocusTrap(container: HTMLElement) => DisposerHält Tab/Umschalt+Tab in container. Tab auf dem letzten fokussierbaren Element springt zum ersten; Umschalt+Tab auf dem ersten springt zum letzten; ein Fokus, der aus dem Container entkommt (Klick außerhalb, programmatischer Fokus), wird zurückgeholt. Verschiebt den Fokus beim Aktivieren nicht in den Container — das entscheidet der Aufrufer.
getFocusableElements(container: HTMLElement) => HTMLElement[]Gibt jedes per Tastatur fokussierbare Nachfahrenelement in DOM-Reihenfolge zurück und überspringt deaktivierte, versteckte und Elemente mit tabindex="-1".

Verwendung

typescript
import { captureFocusForReturn, createFocusTrap } from '@reelkit/core';

// When your modal opens:
const restoreFocus = captureFocusForReturn();
container.focus({ preventScroll: true });
const releaseTrap = createFocusTrap(container);

// When the modal closes:
releaseTrap();
restoreFocus();

Video-Hilfsfunktionen

Hilfsfunktionen für eine gemeinsame Videowiedergabe über Slides hinweg, unabhängig vom Framework. Intern von @reelkit/react-reel-player und @reelkit/react-lightbox genutzt und für eigene Bindings von Frameworks verfügbar.

ExportTypBeschreibung
captureFrame(video: HTMLVideoElement) => string | nullHält den aktuellen Videoframe als JPEG-Data-URL fest. Gibt bei Fehlern durch einen fremden Origin null zurück.
createSharedVideo(config: SharedVideoConfig) => SharedVideoInstanceErstellt ein abgegrenztes gemeinsames Video-Singleton mit Maps für Wiedergabeposition und festgehaltene Frames. Jeder Nutzer bekommt eine eigene Instanz, damit der Ton auf iOS durchgehend bleibt.
syncVideoObjectFit(video: HTMLVideoElement, fallbackIsVertical: boolean) => DisposerHält video.style.objectFit mit der echten Ausrichtung des Videos synchron. Wendet den Fallback (aus dem angegebenen Seitenverhältnis) sofort an, liest dann bei loadedmetadata die echten Werte videoWidth / videoHeight und wechselt bei Hochformat zu 'cover', bei Querformat zu 'contain'. Robust gegen falsch angegebene Metadaten.

URL-State

Spiegelt einen Query-Parameter in ein Signal und zurück. Zwei Achsen mit je einer Aufgabe: Ein codec ist das Format in der URL (Text des Parameters ↔ eine stabile Identität), ein locator ist die Suche (wo diese Identität in der Sammlung steht).

ExportTypBeschreibung
createUrlStateController({ param, adapter?, codec?, locator? }) => UrlStateControllerSpiegelt einen Query-Parameter in ein Signal und schreibt Änderungen zurück in die URL. Das erste Schreiben eines fehlenden Parameters legt einen Eintrag im Verlauf an; jedes Schreiben danach ersetzt ihn. Mit einem codec oder locator leitet er auch position: Signal<Pos | null> ab, wendet die Sperre für Öffnen und Schließen an und entfernt einen Parameter, der keinen Slide benennt, selbst — so abonniert jedes Binding, statt neu abzuleiten. Das Schreiben einer Position im geschlossenen Zustand öffnet sofort, ohne darauf zu warten, dass der Adapter das Schreiben zurückmeldet; UrlChange sagt, ob ein Schließen einen Schritt zurückgeht oder an Ort und Stelle leert.
createHistoryAdapter() => UrlAdapterStandardadapter über die History-API. Eine Anwendung mit Router sollte stattdessen einen eigenen übergeben, sonst veraltet die Location des Routers und seine nächste Navigation verliert den Parameter.
indexCodecUrlCodec<number>Liest ?photo=3 als Slide 3. Übergib ihn, um die Ableitung über den Index zu nutzen, ohne einen eigenen Codec zu schreiben. Für eine endlose oder seitenweise Liste übergib stattdessen locator — der Parameter überlebt, solange das Promise aussteht, sodass ein Deep Link in eine noch nicht geladene Seite nicht mitten im Abruf gelöscht wird.
createIndexLocator(countGetter: () => number) => UrlLocator<number>Der Standard-Locator für Indizes: Eine Slide-Position steht für sich selbst, begrenzt durch die aktuelle Anzahl, die der Getter liefert. Ein Index außerhalb des Bereichs wird zu null, sodass sich ein veraltetes ?photo=99 selbst aus der URL entfernt — er lehnt ab, statt auf den nächsten Slide zu runden, was einen Slide öffnen würde, den die URL nie benannt hat. Ein Getter statt einer Zahl, damit die Grenze beim Nachschlagen die aktuelle Größe liest, während eine seitenweise Galerie wächst.
urlIndexKey(countGetter, locateAsync?) => UrlKey<number>Das passende Paar für eine Galerie, die über Indizes adressiert wird — indexCodec plus ein createIndexLocator, der an die Größe der Galerie gebunden ist. Übergib es per Spread ({ param, ...urlIndexKey(() => count) }), damit der Codec nicht vom Locator abweicht. Übergib ein zweites Argument locateAsync, um einen seitenweisen Feed zu fenstern — bei einem Fehltreffer bis zum gesuchten Index nachladen und ihn dann zurückgeben.
urlIndexTwoAxisKey(opts) => UrlKey<TwoAxisIdentity, TwoAxisPosition>Wie urlIndexKey, aber für einen Player mit zwei Achsen: ein strikt mit Punkt getrennter Parameter ?p=<outer>.<inner>, der zu einer TwoAxisPosition { outer, inner } aufgelöst wird. Optionen (UrlIndexTwoAxisKeyOptions): outerCount, innerCounts, optional outerCodec/outerLocator für die äußere Achse und innerCodec/innerLocate/innerIdentify, um auch die innere Achse über IDs zu adressieren. Jede Achse nutzt standardmäßig eine einfache Grenze über den Index. Treibt den Stories Player mit URL-Steuerung an.
createStableIdCodec(hashCodec?: UrlCodec<string>) => UrlCodec<string>Das Format für stabile IDs, exportiert zum Kombinieren — der Text des Parameters ist die id des Elements, roh geschrieben oder durch hashCodec umgewandelt (übergib base64UrlCodec für umkehrbares base64url). Das Gegenstück zu indexCodec für stabile IDs: Kombiniere es mit einem eigenen Locator, statt den ganzen urlStableIdKey zu nehmen.
base64UrlCodecUrlCodec<string>Der fertige Mechanismus zum Verschleiern für einen Key über stabile IDs: umkehrbares base64url (URL-sicheres Alphabet, kein Padding, UTF-8) — kein kryptografischer Hash. Übergib ihn als hashCodec, um die ID in der URL zu verschleiern, oder implementiere einen eigenen UrlCodec<string> für ein anderes Verfahren.
createStableIdLocator(items, locateAsync?) => UrlLocator<string, number>Die Suche für stabile IDs, exportiert zum Kombinieren — durchsucht items() nach einer passenden id; eine verschwundene ID wird zu null und entfernt sich selbst. Das optionale locateAsync fenstert einen seitenweisen Feed. Das Gegenstück zu createIndexLocator für stabile IDs.
urlStableIdKey(opts) => UrlKey<string, number>Adressiert eine Galerie über die stabile id jedes Elements — ?photo=<id> — statt über die Position, sodass ein Lesezeichen eine Neusortierung der Liste übersteht. Optionen (UrlStableIdKeyOptions): items (ein Getter auf die aktuelle Liste), optional hashCodec (übergib base64UrlCodec), um die ID in der URL umzuwandeln, optional locateAsync, um einen seitenweisen Feed zu fenstern (bei einem Fehltreffer laden, bis die ID da ist, dann ihren Index zurückgeben). Ziehe ihn urlIndexKey vor, wann immer sich die Liste unter einem geteilten Link ändern kann.
urlStableIdTwoAxisKey(opts) => UrlKey<TwoAxisIdentity<string>, TwoAxisPosition>Das Gegenstück mit zwei Achsen: die äußere Achse über eine stabile ID, die innere über einen lokalen Index — ?story=user_42.3. Übergib innerItems statt innerCounts, um auch die innere Achse über IDs zu adressieren (?story=user_42.photo_7); hashCodec (zum Beispiel base64UrlCodec) wandelt beide IDs um. Optionen UrlStableIdTwoAxisKeyOptions (innerer Index) oder UrlStableIdTwoAxisIdInnerOptions (innere ID); Elementtypen erfüllen Identified ({ id: string }).
UrlCodec<Id>{ decode(raw) => Id | null; encode(id) => string }Das Format in der URL: Text des Parameters ↔ eine stabile Identität, ohne Kenntnis der Sammlung. Gibt decode null zurück, ist der Text fehlerhaft.
UrlLocator<Id>{ locate(id) => number | null; locateAsync?(id) => Promise<number | null>; identify(index) => id }Die Suche: wo die Identität in der Sammlung steht. locate ist synchron, locateAsync sein Fallback für eine seitenweise Liste, und identify macht aus einem Index für das Schreiben wieder eine Identität.
UrlKey<Id>{ codec: UrlCodec<Id>; locator: UrlLocator<Id> }Das passende Paar aus Codec und Locator für einen Parameter. Sie teilen dasselbe Id und gehören immer zusammen — der Codec schreibt die Identität in die URL, der Locator findet, wo sie steht —, und sie als Paar zu bauen ist das, was sie davon abhält, sich zu widersprechen.
UrlAdapter{ read, subscribe, push, replace, getState, goBack }Der Einstiegspunkt für einen Router. Eine Anwendung mit Router muss einen übergeben, sonst veraltet die eigene Location des Routers. Der Listener von subscribe nimmt ein optionales UrlChange; ein Aufruf ohne Argument ist immer gültig und bedeutet, dass der Adapter nicht sagen kann, wie der Eintrag aktuell wurde.
UrlChange{ kind?: 'push' | 'replace' | 'pop' }Was ein Adapter über die Navigation weiß, die gerade angekommen ist. Melde push nur für eine Navigation, die der Router selbst auf derselben Seite gemacht hat; das ist der einzige Fall, in dem das Schließen den Eintrag entfernen darf. Ohne Beleg wird der Eintrag nie beansprucht, und das Schließen leert den Parameter an Ort und Stelle, sodass ein Duplikat der Seite im Verlauf bleibt, statt einen Schritt aus der Website hinaus zu riskieren.
UrlStateOptions<Id>{ param: string; adapter?: UrlAdapter; codec?: UrlCodec<Id>; locator?: UrlLocator<Id> }Die Optionen, die createUrlStateController nimmt — exportiert, damit ein Nutzer eine separat zusammengestellte Konfiguration typisieren kann, bevor er sie übergibt.

Gesehen-Status

Speichert, wie weit ein Nutzer gekommen ist, mit demselben Key wie die Adresszeile: Ein Eintrag ist der Text des Parameters selbst und wird über denselben codec und locator zurückgelesen.

ExportTypBeschreibung
createViewedStateController(options) => ViewedStateController<Pos>Merkt sich, wie weit ein Nutzer gekommen ist, gespeichert als genau der Text, den ein URL-Parameter tragen würde. Nimmt dasselbe Paar codec/locator, das die Adresszeile nutzt, dazu storageKey, optional storage, trackOf (ein Eintrag pro Gruppe) und progressOf. Liest nichts vor attach() und ist deshalb sicher fürs Prerendering.
twoAxisViewedTracking{ trackOf, progressOf }Das Tracking-Paar für einen Player mit zwei Achsen: ein Eintrag pro äußerem Platz, der innere Index misst den Fortschritt darin. Übergib es per Spread neben einem Key mit zwei Achsen.
createLocalStorageAdapter() => StorageAdapterDer Standardspeicher. Dazu createSessionStorageAdapter für einen Zustand, der den Tab nicht überdauern soll, und createMemoryStorageAdapter für Tests und Server-Rendering. Jeder fängt seine eigenen Fehler ab — ein erschöpftes Kontingent verliert diesen einen Schreibvorgang und nicht mehr.
ViewedStateController<Pos>{ entries; resolve(track); record(position); forget(track?); attach() }entries ist ein Signal von Track → gespeichertem Text, sodass ein Ring neu zeichnet, wenn hier oder in einem anderen Tab eine Position erfasst wird. resolve durchläuft bei jedem Aufruf den vollen Ablauf des Keys.
ViewedStateOptions<Id, Pos>{ storageKey; codec; locator; storage?; trackOf?; progressOf; ttlMs?; maxTracks? }Die Optionen, die createViewedStateController nimmt — exportiert, damit ein Nutzer eine separat zusammengestellte Konfiguration typisieren kann, bevor er sie übergibt. progressOf ist nur für eine einfache Position über den Index optional, die selbst ihr Maß für den Fortschritt ist; jede andere Position muss sagen, welche Zahl verglichen wird, und der Typ verlangt es. ttlMs schaltet den Ablauf ein: Ein Track wird so lange nach seiner letzten Erfassung vergessen, und eine erneute Erfassung startet seine Uhr neu. maxTracks behält höchstens so viele Tracks und entfernt beim nächsten Schreiben den am längsten nicht erfassten.
StorageAdapter{ read(key); write(key, value); subscribe?(key, listener) }Der Einstiegspunkt für eine Speicherschicht. Lässt du subscribe weg, läuft der Speicher einfach ohne Synchronisation zwischen Tabs.