import * as _angular_core from '@angular/core'; import { InjectionToken, Signal, Provider } from '@angular/core'; import { WritingDirection, RovingTabindex, ListNavigationAction } from 'forty-cdk/core'; /** Alignment of the active slide within the viewport. */ type CarouselAlign = 'start' | 'center' | 'end'; /** * Internal handle for a registered slide. Part of the registration protocol, so * it is never exported from `public-api.ts` — see {@link CarouselContext}. */ interface ForCarouselSlideHandle { readonly host: HTMLElement; } /** * Internal handle for a registered indicator (dot). Part of the registration * protocol, so it is never exported from `public-api.ts` — see * {@link CarouselContext}. */ interface ForCarouselIndicatorHandle { readonly host: HTMLElement; readonly disabled: Signal; } /** * Internal handle for the registered viewport. Part of the registration * protocol, so it is never exported from `public-api.ts` — see * {@link CarouselContext}. */ interface ForCarouselViewportHandle { readonly host: HTMLElement; readonly id: string; } /** * Coordination contract owned by `ForCarousel`. Slides and indicators * register with the root so index lookups, geometry computations, and * keyboard navigation are all driven from a single source of truth. */ interface ForCarouselContext { readonly activeIndex: Signal; readonly orientation: Signal<'horizontal' | 'vertical'>; readonly dir: Signal; readonly loop: Signal; readonly align: Signal; readonly slidesPerView: Signal; readonly slideCount: Signal; /** Whether auto-rotation is currently "on" (user intent). Drives the rotation control's label. */ readonly playing: Signal; /** Whether the carousel is actively auto-rotating right now (`playing && !paused`). Drives the viewport's `aria-live`. */ readonly rotating: Signal; canScrollPrev(): boolean; canScrollNext(): boolean; scrollPrev(): void; scrollNext(): void; scrollTo(index: number): void; /** Toggle auto-rotation on/off (the explicit, sticky user choice). Called by the rotation control. */ toggleAutoplay(): void; isCurrent(index: number): boolean; isFirstEnabledIndicator(el: HTMLElement): boolean; hasCurrentIndicator(): boolean; } /** * The carousel's piece-coordination surface: the roving tracker the indicators * share, the DOM-order index lookups, the viewport id the rotation control * points `aria-controls` at, and the localizable positional labels. * * **Not** part of {@link ForCarouselContext} and never exported * from `public-api.ts` — a consumer drives the carousel through `scrollTo` / * `scrollNext`, never through the indicators' shared tab stop. */ interface CarouselPieceContext { readonly roving: RovingTabindex; navigate(currentIndicator: HTMLElement, action: ListNavigationAction): void; viewportId(): string | null; indexOfSlide(host: HTMLElement): number; indexOfIndicator(host: HTMLElement): number; /** Resolve the positional slide `aria-label` (`"N of M"` by default). `position` is 1-based. */ slideLabel(position: number): string; /** Resolve the indicator `aria-label` (`"Go to slide N"` by default). `position` is 1-based. */ indicatorLabel(position: number): string; isInView(index: number): boolean; } /** * DI token providing the carousel context to descendant pieces. * * Publicly typed as the read surface {@link ForCarouselContext}, which is the whole of * what the token promises a consumer. The pieces read the same token at an internal type * that adds the slide / indicator / viewport registration protocol, so a wrapper * re-providing it must alias it to the root: `{ provide: FOR_CAROUSEL_CONTEXT, * useExisting: MyCarousel }`, where `MyCarousel` extends `ForCarousel`. A value that * merely satisfies the declared type resolves too, and is rejected in dev mode by the * first piece to reach the protocol. */ declare const FOR_CAROUSEL_CONTEXT: InjectionToken; /** * The carousel's internal coordination surface: everything * {@link ForCarouselContext} publishes plus the {@link CarouselPieceContext} * members and the slide / indicator / viewport registration protocol the index * lookups, geometry observer and roving tabindex are driven from. * * Never exported from `public-api.ts`. It is the type the pieces read * {@link FOR_CAROUSEL_CONTEXT} at, so a consumer who injects that token gets the * read surface while the pieces get the wiring protocol. `ForCarousel` declares * the protocol members TS-`private`, which keeps them out of the emitted * `.d.ts` while `useExisting` still satisfies this contract at runtime. */ interface CarouselContext extends ForCarouselContext, CarouselPieceContext { registerSlide(handle: ForCarouselSlideHandle): void; unregisterSlide(handle: ForCarouselSlideHandle): void; registerIndicator(handle: ForCarouselIndicatorHandle): void; unregisterIndicator(handle: ForCarouselIndicatorHandle): void; registerViewport(handle: ForCarouselViewportHandle): void; unregisterViewport(handle: ForCarouselViewportHandle): void; } /** * Root of the Carousel primitive. Owns the active index, slide collection, * indicator collection, roving tabindex tracker, and computed geometry CSS * variables. Provides the shared context to descendant pieces. * * Implements the [WAI-ARIA APG Carousel pattern](https://www.w3.org/WAI/ARIA/apg/patterns/carousel/). * * With no `[forCarouselIndicators]` rendered this is a basic carousel driven * by prev/next buttons only. Adding an indicator group enables APG picker * semantics: roving tabindex, arrow/Home/End navigation with automatic * activation. */ declare class ForCarousel implements ForCarouselContext { #private; /** * Two-way bindable. The zero-based index of the current (leading) slide. * The `model()` change emitter (`(activeIndexChange)`) fires only on internal * navigation (prev/next button clicks, indicator arrow-key or click), never * on consumer writes via `[(activeIndex)]`. */ readonly activeIndex: _angular_core.ModelSignal; /** Scroll axis. `'horizontal'` (default) or `'vertical'`. */ readonly orientation: _angular_core.InputSignal<"horizontal" | "vertical">; /** * Whether index wrap-around is enabled. When `true`, `next` past the last * slide wraps to index 0; `prev` before index 0 wraps to the last. Default * comes from `provideForCarouselDefaults` or the library fallback (`false`). */ readonly loop: _angular_core.InputSignalWithTransform; /** * Alignment of the active slide within the viewport. Affects the * `--for-carousel-offset` computation. Default from `provideForCarouselDefaults` * or `'start'`. */ readonly align: _angular_core.InputSignal; /** * Number of slides simultaneously visible in the viewport. Slide width * should be set to `calc(100% / var(--for-carousel-slides-per-view))` in * the consumer's CSS. Default from `provideForCarouselDefaults` or `1`. */ readonly slidesPerView: _angular_core.InputSignalWithTransform; /** * When `true` and the carousel is not looping, clamps `--for-carousel-offset` so the * trailing slides align flush to the viewport's trailing edge instead of overscrolling * into empty space (relevant when `slidesPerView > 1`). The one-indicator-per-slide * mapping is preserved — `activeIndex` still reaches the last slide; only the visual * offset is contained. No effect when `loop` is enabled or `slidesPerView` is 1. * Default from `provideForCarouselDefaults` or `false`. */ readonly containScroll: _angular_core.InputSignalWithTransform; /** * Accessible label for the carousel root (`role="group"`). Should describe * the carousel's purpose without using the word "carousel" (APG guidance). * When null (default), no `aria-label` is emitted; use `aria-labelledby` * instead when a visible heading labels the carousel. */ readonly ariaLabel: _angular_core.InputSignal; protected readonly resolvedAriaLabel: _angular_core.Signal; /** * Whether the carousel auto-rotates. When `true` and the user has not * explicitly stopped it, rotation starts on mount — *unless* * `prefers-reduced-motion: reduce` is set, which suppresses auto-start * (the user can still start it via the rotation control). Default from * `provideForCarouselDefaults` or `false`. * * APG requires a `[forCarouselRotationControl]` to be present whenever * autoplay is enabled. The directive does not enforce this — see the README. */ readonly autoplay: _angular_core.InputSignalWithTransform; /** * Milliseconds between automatic slide advances while rotating. Values * `<= 0` disable the timer. Default from `provideForCarouselDefaults` or `5000`. */ readonly autoplayInterval: _angular_core.InputSignalWithTransform; /** * Writing direction. When unset (default `null`), the inherited ambient * direction is resolved from the nearest ancestor carrying a `dir` attribute * (or ``), defaulting to `'ltr'`. An explicit `[dir]` always wins. * The resolved value is reflected to the host `dir` attribute and swaps * ArrowLeft / ArrowRight semantics on the indicator group in RTL. */ readonly _dirInput: _angular_core.InputSignal; readonly dir: _angular_core.Signal; /** Roving tabindex tracker for the indicator group. */ private readonly roving; /** Whether auto-rotation is "on" (user intent). Sticky once the user decides. */ readonly playing: _angular_core.Signal; /** Whether the carousel is actively auto-rotating right now. */ readonly rotating: _angular_core.Signal; /** Total number of registered slides. Reactive. */ readonly slideCount: _angular_core.Signal; /** * The `--for-carousel-offset` value to apply via `transform` on the track. * Pure arithmetic — no layout measurement — so it is safe in Vitest. */ readonly offset: _angular_core.Signal; /** The measured viewport width, or `null` before first measurement / on the server. */ readonly viewportWidth: _angular_core.Signal; /** The measured viewport height, or `null` before first measurement / on the server. */ readonly viewportHeight: _angular_core.Signal; constructor(); /** Returns `true` when scrolling backward is possible given the current loop/index state. */ canScrollPrev(): boolean; /** Returns `true` when scrolling forward is possible given the current loop/index state. */ canScrollNext(): boolean; /** Navigate to the previous slide. No-op at index 0 when not looping. */ scrollPrev(): void; /** Navigate to the next slide. No-op at the last index when not looping. */ scrollNext(): void; /** * Navigate to the slide at `index`. Clamps to `[0, slideCount-1]` when not * looping; wraps modulo `slideCount` when looping. */ scrollTo(index: number): void; /** * Move focus from `currentIndicator` according to `action` and activate the * target slide (automatic activation). Used by `ForCarouselIndicator`'s * keydown handler. */ private navigate; private registerSlide; private unregisterSlide; private registerIndicator; private unregisterIndicator; /** Called by `ForCarouselViewport` at construction to wire the geometry observer. */ private registerViewport; /** * Called by `ForCarouselViewport` on destroy so an unmounted viewport stops * being observed and prev / next drop their stale `aria-controls`. */ private unregisterViewport; /** The id of the registered viewport element, or `null` if none is mounted. */ private viewportId; /** DOM-order index of the registered slide whose host equals `host`, or -1. */ private indexOfSlide; /** DOM-order index of the registered indicator whose host equals `host`, or -1. */ private indexOfIndicator; /** * Resolve the positional slide `aria-label` from the scope's defaults * (`"N of M"` unless localized via `provideForCarouselDefaults`). * `position` is the 1-based slide index. */ private slideLabel; /** * Resolve the indicator `aria-label` from the scope's defaults * (`"Go to slide N"` unless localized via `provideForCarouselDefaults`). * `position` is the 1-based slide index. */ private indicatorLabel; /** Returns `true` when `index` is the current active slide index. */ isCurrent(index: number): boolean; /** * Returns `true` when `index` falls within the visible window * `[activeIndex, activeIndex + slidesPerView - 1]`. */ private isInView; /** * Returns `true` when `el` is the host of the first non-disabled indicator * in DOM order. Used by the tabindex fallback when no indicator is current. */ isFirstEnabledIndicator(el: HTMLElement): boolean; /** * Returns `true` when at least one registered, non-disabled indicator * matches the current `activeIndex`. Used by the tabindex ladder to decide * whether the first-enabled fallback must reclaim the tab stop. * * Assumes the one-indicator-per-slide mapping the rest of the picker is built * on: the indicator at DOM index `i` targets slide `i`. A mismatched indicator * count is dev-guarded at construction by the `FORCDK-CAROUSEL-002` warning. */ hasCurrentIndicator(): boolean; /** Start auto-rotation (explicit, sticky). Overrides the reduced-motion auto-start gate. */ play(): void; /** Stop auto-rotation (explicit, sticky). Hover/focus/visibility changes will not restart it. */ pause(): void; /** Toggle auto-rotation. Called by `[forCarouselRotationControl]`. */ toggleAutoplay(): void; protected onAutoplayPause(reason: 'hover' | 'focus'): void; protected onAutoplayResume(reason: 'hover' | 'focus'): void; protected onAutoplayFocusOut(event: FocusEvent): void; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * Clips the visible window of the carousel track. Acts as the APG-mandated * live region for screen-reader announcements. `aria-live` flips between * `"off"` while the carousel is actively auto-rotating (so advancing slides * do not bombard the screen reader) and `"polite"` at all other times so * manual navigation is announced. Also serves as the `aria-controls` target * for the prev/next buttons. * * Registers itself with the carousel root on construction so the root's * `injectElementSize` observer starts and prev/next's `aria-controls` resolves. * There must be exactly one viewport per carousel. Unregisters on destroy, so * an unmounted viewport stops being observed and prev / next stop pointing * `aria-controls` at a dead id. */ declare class ForCarouselViewport { #private; protected readonly ctx: CarouselContext; /** The resolved id of this element — generated or adopted from a consumer-set static `id`. */ readonly id: _angular_core.Signal; constructor(); static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * The flex container of slides. The consumer's CSS reads * `--for-carousel-offset` (inherited from the root) and applies it as a * `transform: translateX(...)` / `translateY(...)` on this element. * The directive adds no animation or transform itself. * * Reflects `data-orientation` so the consumer can select the correct CSS * axis via `[data-orientation="vertical"] [forCarouselTrack] { ... }`. */ declare class ForCarouselTrack { protected readonly ctx: CarouselContext; static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * One slide in the carousel track. Carries `role="group"` and * `aria-roledescription="slide"` per the WAI-ARIA APG Carousel pattern. * * The default `aria-label` is the positional `"N of M"` string (APG mandates * a positional label on each slide). Set `ariaLabel` to override with a * semantically richer label for the specific slide content. * * Off-view slides (outside `[activeIndex, activeIndex + slidesPerView - 1]`) * are hidden from the accessibility tree and focus order via * `aria-hidden="true"` + `inert`. */ declare class ForCarouselSlide { #private; protected readonly ctx: CarouselContext; /** * Override the default positional `aria-label` (`"N of M"`). Use this to * provide a semantically richer label when the slide's content has a * meaningful title (e.g. the product name). When `null` (default), the * positional label is used automatically. Localize that default format * app-wide via `provideForCarouselDefaults`'s `slideLabel`. */ readonly ariaLabel: _angular_core.InputSignal; /** Whether this is the current (active) slide. */ protected readonly current: _angular_core.Signal; /** Whether this slide is within the visible window. */ protected readonly inView: _angular_core.Signal; /** The positional `"N of M"` label used when no explicit `ariaLabel` is set. */ protected readonly positionLabel: _angular_core.Signal; constructor(); static ɵfac: _angular_core.ɵɵFactoryDeclaration; static ɵdir: _angular_core.ɵɵDirectiveDeclaration; } /** * Previous-slide button. Apply on a `