Angular API Reference

Complete reference for @reelkit/angular components, directives, services, and utilities.

ReelComponent

Selector: rk-reel

Inputs

InputTypeDefaultDescription
countnumberrequiredTotal number of slides
direction'vertical' | 'horizontal''vertical'Scroll direction
size[number, number] | undefinedundefinedWidth and height as [width, height]. When omitted, auto-measures via ResizeObserver
initialIndexnumber0Starting slide index
loopbooleanfalseEnable infinite loop
transitionTransitionTransformFnslideTransitionTransition effect function. Built-in: slideTransition, fadeTransition, flipTransition, cubeTransition, zoomTransition
transitionDurationnumber300Animation duration in ms
swipeDistanceFactornumber0.12Swipe threshold (0-1)
enableGesturesbooleantrueEnable touch/mouse drag navigation
enableNavKeysbooleantrueEnable keyboard arrow key navigation
enableWheelbooleanfalseEnable mouse wheel navigation
wheelDebounceMsnumber200Wheel event debounce in ms
rangeExtractor(index: number, count: number) => number[]defaultRangeExtractorCustom function to determine which indexes are rendered
keyExtractor(index: number, indexInRange: number) => string | numberindex => indexCustom key function for @for track expressions (useful with loop)
classNamestring''CSS class applied to the root container element
ariaLabelstring'Carousel'Accessible label for the carousel region

Outputs

OutputTypeDescription
afterChangeEventEmitter<{ index: number; indexInRange: number }>Emitted after slide transition completes
beforeChangeEventEmitter<{ index: number; nextIndex: number; indexInRange: number }>Emitted before slide transition begins
slideDragStartEventEmitter<number>Emitted when a drag gesture starts
slideDragEndEventEmitter<number>Emitted when a drag gesture ends (released)
slideDragCanceledEventEmitter<number>Emitted when a drag gesture is canceled (snap-back)
apiReadyEventEmitter<ReelApi>Emitted once after view init, exposing the imperative API

ReelApi Interface

Obtained via the (apiReady) output:

typescript
import { type ReelApi } from '@reelkit/angular';

@Component({ ... })
export class AppComponent {
  api: ReelApi | undefined;

  // In template: (apiReady)="api = $event"

  prev()  { this.api?.prev(); }
  next()  { this.api?.next(); }
  jump(i: number) { this.api?.goTo(i, true); }  // animated
}
MethodTypeDescription
next()() => voidGo to next slide
prev()() => voidGo to previous slide
goTo(index, animate?)(number, boolean?) => Promise<void>Navigate to a specific slide index
adjust()() => voidRecalculate slide positions (useful after layout change)
observe()() => voidStart listening to keyboard events
unobserve()() => voidStop listening to keyboard events

RkReelItemDirective

Selector: [rkReelItem] — Applied to an ng-template inside rk-reel.

Template Context

html
<ng-template rkReelItem let-i let-indexInRange="indexInRange" let-size="size">
  <!-- $implicit (let-i)  : number         — absolute slide index -->
  <!-- indexInRange        : number         — position in the visible window (0, 1, or 2) -->
  <!-- size                : [number,number] — [width, height] of the container -->
</ng-template>
VariableTypeDescription
$implicit (let-i)numberAbsolute slide index (0 to count-1)
indexInRangenumberPosition in the visible window (0, 1, or 2)
size[number, number]Current slider dimensions as [width, height] in pixels

ReelIndicatorComponent

Selector: rk-reel-indicator

Inputs

InputTypeDefaultDescription
countnumber | undefinedautoTotal number of items. Auto-connected from parent rk-reel context when nested inside one; pass explicitly when used standalone
activenumber | undefinedautoCurrent active index. Auto-connected from parent rk-reel context when nested inside one; pass explicitly when used standalone
direction'vertical' | 'horizontal''vertical'Indicator orientation
radiusnumber3Dot radius in pixels
visiblenumber5Max normal-sized dots visible at once
gapnumber4Space between dots in pixels
activeColorstring'#fff'Active dot color
inactiveColorstring'rgba(255,255,255,0.5)'Inactive dot color
edgeScalenumber0.5Scale factor for edge overflow dots
classNamestring''Custom CSS class applied to the indicator container
tablistLabelstring'Slide navigation'Accessible label for the tablist landmark

Outputs

OutputTypeDescription
dotClickEventEmitter<number>Emitted when a dot is clicked; provides the dot index

RK_REEL_CONTEXT

An InjectionToken<ReelContextValue> provided by rk-reel to its descendants. Used internally by rk-reel-indicator for auto-connect behavior. Inject it in custom components that need slider context.

typescript
import { inject } from '@angular/core';
import { RK_REEL_CONTEXT } from '@reelkit/angular';

@Component({ ... })
export class MyCustomControl {
  private readonly ctx = inject(RK_REEL_CONTEXT, { optional: true });

  jump(index: number) {
    this.ctx?.goTo(index, true);
  }
}
PropertyTypeDescription
indexSignal<number>Reactive current slide index
countSignal<number>Reactive total item count
goTo(index: number, animate?: boolean) => Promise<void>Programmatically navigate to a slide

BodyLockService

Reference-counted body scroll lock. Multiple concurrent callers (e.g. a lightbox and a modal both open) can each call lock/unlock independently — the body is only restored once the last caller releases it. Provided at root — inject anywhere.

typescript
import { inject } from '@angular/core';
import { BodyLockService } from '@reelkit/angular';

@Component({ ... })
export class OverlayComponent {
  private readonly bodyLock = inject(BodyLockService);

  open() { this.bodyLock.lock(); }
  close() { this.bodyLock.unlock(); }
}
MemberTypeDescription
lockedboolean (getter)Whether the body is currently locked
lock()() => voidLock body scroll and apply scrollbar width compensation
unlock()() => voidRestore original body scroll styles

SoundStateService

Muted and disabled state for an overlay that plays media, as Angular signals. Provide it on the component that owns the media rather than at root, so each overlay instance keeps its own state. Every reelkit Angular overlay uses it — @reelkit/angular-reel-player re-exports the same class, so an existing import from there keeps working.

The lightbox is the exception: provide it above <rk-lightbox-overlay>, since its video slide renders from your own template and would otherwise never see the instance inside the overlay.

typescript
import { inject } from '@angular/core';
import { SoundStateService } from '@reelkit/angular';

@Component({
  // Provide it on the component that owns the media, so two overlays
  // on one page never share a muted state.
  providers: [SoundStateService],
  // ...
})
export class OverlayComponent {
  readonly soundState = inject(SoundStateService);

  // Use in template:
  // [muted]="soundState.muted()"
  // [hidden]="soundState.disabled()"
  // (click)="soundState.toggle()"
}
MemberTypeDescription
muted()Signal<boolean>Whether audio is currently muted. Starts muted
disabled()Signal<boolean>True while sound cannot be controlled, and the sound button hides. The overlay sets it — RkReelPlayerOverlayComponent raises it while a slide has no video or is mid-transition
controllerSoundController (getter)The core SoundController underneath — hand it to syncMutedToVideo to keep a <video> in step with the muted state
toggle()() => voidToggles the muted state
setDisabled()(value: boolean) => voidSets whether sound is controllable right now
reset()() => voidReturns to the starting state: muted, not disabled

Signal Bridge Utilities

Utility functions that bridge the core signal system (@reelkit/core) with Angular's native signal API. Used internally by ReelComponent; also available for custom framework integrations.

FunctionSignatureDescription
toAngularSignal(source: Subscribable<T>, destroyRef: DestroyRef) => Signal<T>Bridges a core Subscribable into a read-only Angular Signal
animatedSignalBridge(source: AnimatedValue, zone: NgZone, cdRef: ChangeDetectorRef, destroyRef: DestroyRef) => Signal<number>Bridges a core animated value into an Angular Signal, updating via requestAnimationFrame outside the zone
typescript
import { DestroyRef, inject } from '@angular/core';
import { toAngularSignal } from '@reelkit/angular';
import { createSliderController } from '@reelkit/core';

// Custom component using low-level signal bridge
const destroyRef = inject(DestroyRef);
const controller = createSliderController({ count: 10 }, {});
const index = toAngularSignal(controller.state.index, destroyRef);

createOverlayUrlState

OverlayUrlStateOptions

Builds a URL-state controller for an overlay, which you hand to <rk-lightbox-url-overlay> as its [controller] input. Call it in an injection context — a field initialiser or the constructor; it attaches immediately and releases through DestroyRef. Walkthrough: URL State on the Angular Lightbox page.

OptionTypeDefaultDescription
paramstringrequiredQuery parameter carrying the active slide, e.g. photo.
adapterUrlAdapterHistory APINavigation system to read and write through. Pass a Router-backed adapter in a routed app so the Router's location does not go stale.
codecUrlCodec<Id>requiredWire format: param text to a stable identity. Travels with locator as a matched pair — spread ...urlIndexKey(() => images().length) for the default ?photo=3 gallery, or supply your own so a bookmark survives reordering.
locatorUrlLocator<Id>requiredMaps the identity to a position and owns its own validity: locate (sync), locateAsync (async fallback for a paginated gallery), identify (writes).

createRouterUrlAdapter

@reelkit/angular/ng-router-url-adapter

A UrlAdapter backed by the Angular Router. Pass it as the adapter option of createOverlayUrlState in a routed app so the Router stays the single source of navigation truth — writing history.pushState behind the Router leaves its location stale and its next navigation drops the parameter. Writes touch the query only, so the path, the fragment, and repeated keys such as ?tag=a&tag=b ride along untouched. Every change reports whether the Router pushed on the same page, replaced, or stepped through history, so a gallery opened from a routerLink closes with one back step. Call it in an injection context; the router subscription releases through DestroyRef.

Ships from its own subpath, so an app without routing never pulls @angular/router into its bundle. @angular/router is an optional peer dependency.

typescript
import { createRouterUrlAdapter } from '@reelkit/angular/ng-router-url-adapter';

protected readonly photo = createOverlayUrlState({
  param: 'photo',
  adapter: createRouterUrlAdapter(),
  ...urlIndexKey(() => this.images().length),
});

Accessibility

<rk-reel> renders as role="region" with aria-roledescription="carousel". Set the ariaLabel input to give the region a screen-reader name. A polite live region announces "Slide N of M" on every slide change. Inactive slides receive the inert attribute so focus and AT navigation skip them.

<rk-reel-indicator> renders as role="tablist" with roving tabindex on the dots; arrow keys move focus and Enter or Space activates the slide.

Building a custom modal around <rk-reel>? captureFocusForReturn, createFocusTrap, and getFocusableElements are re-exported from @reelkit/angular for focus return and trap.

Package Exports

All public exports from @reelkit/angular:

typescript
// Components & directives
import {
  ReelComponent,
  ReelIndicatorComponent,
  RkReelItemDirective,
  RkSwipeToCloseDirective,
} from '@reelkit/angular';

// Types
import type {
  ReelApi,
  ReelContextValue,
  RkReelItemContext,
  CoreSignal,
  Subscribable,
  AnimatedValue,
  RangeExtractor,
  SliderDirection,
  Disposer,
  DisposableList,
  GestureController,
  SliderController,
  ContentLoadingController,
  ContentPreloader,
  ContentPreloaderConfig,
  SoundController,
  BodyLock,
  TransitionTransformFn,
  SlideTransformStyle,
  SwipeToCloseDirection,
} from '@reelkit/angular';

// Context
import { RK_REEL_CONTEXT } from '@reelkit/angular';

// Services
import { BodyLockService, SoundStateService } from '@reelkit/angular';

// Signal bridges
import { toAngularSignal, animatedSignalBridge } from '@reelkit/angular';

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

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

  // Content loading & preloading
  createContentLoadingController, createContentPreloader,

  // Sound
  createSoundController, syncMutedToVideo,

  // Fullscreen
  fullscreenSignal, requestFullscreen, exitFullscreen,

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

  // Focus management
  captureFocusForReturn, createFocusTrap, getFocusableElements,

  // Slider & gestures
  createSliderController, createGestureController,
  defaultRangeExtractor, createDefaultKeyExtractorForLoop,

  // Video
  captureFrame, createSharedVideo,

  // Utilities
  animate, noop, clamp, abs, first, last, extractRange,
} from '@reelkit/angular';